javascript - 尝试在不使用 eval() 的情况下在 React 中构建通用表单组件
问题描述
我目前正在尝试为我的 React 应用程序编写通用表单组件。我知道那里有很多很棒的库,但在这一点上,它们对我来说似乎都是矫枉过正。
我的主要目标是拥有一个<BasicForm>
我可以使用的组件,方法是传递提交函数props
并传递输入字段和按钮,就像children
每个字段的验证要求一样。
我的<BasicForm>
组件应该处理表单state
, onChange
, onBlur
,onSubmit
等。还应该处理验证(基于我添加为的每个输入类型children
)。
动机是每次需要创建新表单时,我都会感到重复,因为必须一遍又一遍地管理state
输入、验证onChange
和功能。submit
这是我正在使用的代码<Basic Form>
:
BasicForm-Consumer.js
<BasicForm
submitFunction={props.linkEmailAndPassword}
submitAction={'this.props.submitFunction(this.state.passwordOne)'}
>
<PasswordInput
labelText='Password'
name='passwordOne'
placeholder='Enter password...'
min={6}
max={12}
required
/>
<TextInput
labelText='Username'
name='username'
placeholder='Enter username...'
initialValue=''
min={5}
max={10}
required
/>
<button type='submit'>Create Password</button>
</BasicForm>
我最初并没有在这里添加源代码,<BasicForm>
以免这个问题太长,但基本上它处理所有输入children
,React.Children.map
并且它具有每种输入的验证功能,以及处理更改、模糊、提交的功能,等等。它还state
为每个输入字段创建一个。
问题介绍
<BasicForm
submitFunction={props.linkEmailAndPassword}
submitAction={'this.props.submitFunction(this.state.passwordOne)'}
>
从上面的代码片段中可以看出,为了将submitAction
消费者发送到<BasicForm>
,我必须将它包装在一个字符串中,因为它引用的 astate
只存在于<BasicForm>
. 最重要的state
是,我需要提交的特定部分是在<BasicForm>
(在消费者中)之外定义的。
消费者定义应该提交的部分或部分,state
并且在每种情况下都会有所不同,因此我不能将其作为state
任何<BasicForm>
内置的“通用”名称。
所以我作为字符串发送,在里面<BasicForm>
我必须使用最不推荐eval()
的,如下所示:
BasicForm.js
onSubmit(event) {
event.preventDefault();
this.validateAllFields();
eval(this.props.submitAction);
}
正确的问题
eval()
在这种情况下有多糟糕?我这样做是否会将我的应用程序暴露给“恶意黑客”?我是否应该以任何方式对其进行消毒,即使它不是用户输入?还有其他方法吗?我真的很高兴不必每次需要时都从头开始构建表单。现在我只关注字段和验证要求。谢谢你的时间!
额外信息
PS:这是输入组件之一的代码TextInput
。PasswordInput
非常像这样。唯一的区别是type='password'
:
文本输入.js
import React from 'react';
import Label from './Common/Label';
const TextInput = (props) => {
return(
<div>
<Label
name={props.name}
labelText={props.labelText}
>
</Label>
<div>
<input
type='text'
id={props.name}
name={props.name}
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange}
onBlur={props.onBlur}
>
</input>
</div>
{props.isInvalidMsg && <div><span>{props.isInvalidMsg}</span></div>}
</div>
);
};
export default TextInput;
解决方案
Eval 几乎从不受欢迎,因为它会带来安全风险、性能损失并表明存在设计问题。
是否存在安全风险取决于其使用情况。如果评估的表达式有可能直接或间接包含用户输入,则存在安全风险。否则,仅适用于性能和设计问题。
在这种情况下,这意味着BasicForm
未能为父组件提供合理的 API,因此以eval
. 执行此操作的正确方法是回调。
由于父组件通常不应了解BasicForm
实现细节并访问其实例,BasicForm
this
因此不应在回调中可用。BasicForm
道具已经在回调中可用 - 它们在父组件中传递。由于已知它BasicForm
state
包含来自其子输入的值,因此它应该在回调中可用。
所以BasicForm
回调可能看起来像:
<BasicForm
onSubmit={state => props.linkEmailAndPassword(state.passwordOne)}}
...
onSubmit(event) {
event.preventDefault();
this.validateAllFields();
this.props.onSubmit(this.state);
}
如果需要onSubmit
回调来访问BasicForm
其状态以外的任何数据,这意味着该数据也应作为回调参数传递。
推荐阅读
- reactjs - 如何向组件请求操作?
- python-3.x - 在python中,我想使用\b退格,但它显示0x08,如何解决这个问题
- laravel - 布尔值的数据类型不匹配?
- typescript - TypeScript:可以在数组中声明特定的序列类型吗?
- java - 怎么解决onclick无法实现fragment跳转?
- c# - 如何用给定输入中的值替换给定的电子邮件地址?
- javascript - Redux 根据窗口宽度改变状态
- assembly - 为什么我不能使用寄存器访问 as86 中的内存
- javascript - 禁用无穷大规则的科学记数法
- node.js - Docker 容器无法相互访问。获得 CONNECTION_REFUSED