我目前正在尝试为我的React应用程序编写通用表单组件。我知道那里有很多很棒的库,但是就目前而言,它们似乎都对我来说太过强大了。
我的主要目标是拥有一个我可以使用的<BasicForm>
组件,方法是将Submit函数传递为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>
,我必须将其包装在字符串中,因为它引用了仅存在于state
内部的<BasicForm>
。 。最重要的是,我需要提交的特定state
部分是在<BasicForm>
之外(在使用者中)定义的。使用者定义
state
的哪些部分应提交,并且在每种情况下都将有所不同,因此我不能将其作为任何state
内置的“通用” <BasicForm>
名称。 -在。因此,我以字符串形式发送,并且在
<BasicForm>
内必须使用最不推荐的eval()
,如下所示:BasicForm.js
onSubmit(event) {
event.preventDefault();
this.validateAllFields();
eval(this.props.submitAction);
}
正确的问题
在这种情况下
eval()
有多糟糕?通过这样做,我是否会将我的应用程序暴露给“恶意黑客”?即使不是用户输入,也应该以任何方式对其进行消毒吗?还有其他解决方法吗?我真的很高兴,不必每次都需要从头开始构建表单。现在,我仅关注字段和验证要求。谢谢你的时间!额外信息
附注:这是输入组件
TextInput
之一的代码。 PasswordInput
非常像这样。唯一的区别是type='password'
:TextInput.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
数据,这意味着该数据也应作为回调参数传递。