尝试在React中构建通用表单组件,而不使用eval()

时间:2019-01-29 10:03:34

标签: javascript reactjs forms

我目前正在尝试为我的React应用程序编写通用表单组件。我知道那里有很多很棒的库,但是就目前而言,它们似乎都对我来说太过强大了。

我的主要目标是拥有一个我可以使用的<BasicForm>组件,方法是将Submit函数作为props传递,并将输入字段和按钮作为children以及验证要求一起传递每个字段。

我的<BasicForm>组件应处理以下形式:stateonChangeonBluronSubmit等。并且还应处理验证(基于每个输入我添加为children的类型。

这样做的动机是,每次需要创建state来进行输入,验证,onChangesubmit的功能时,每次创建新表单时我都会感到重复。

这是我使用<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的哪一部分应提交,并且在每种情况下都将有所不同,因此我不能将其作为任何{ {1}}将具有内置功能。<​​/ p>

因此,我以字符串形式发送,并且在state内部,我不得不使用最不推荐的<BasicForm>,如下所示:

BasicForm.js

<BasicForm>

正确的问题

在这种情况下,eval()有多糟糕?通过这样做,我是否会将我的应用程序暴露给“恶意黑客”?即使不是用户输入,也应该以任何方式对其进行消毒吗?还有其他解决方法吗?我真的很高兴,不必每次都需要从头开始构建表单。现在,我仅关注字段和验证要求。谢谢您的宝贵时间!

额外信息

P.S .:这是输入组件 onSubmit(event) { event.preventDefault(); this.validateAllFields(); eval(this.props.submitAction); } 之一的代码。 eval()就是这样。唯一的区别是TextInput

TextInput.js

PasswordInput

1 个答案:

答案 0 :(得分:3)

几乎永远不会评估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数据,这意味着该数据也应作为回调参数传递。