我目前正在尝试为我的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的哪些部分应提交,并且在每种情况下都将有所不同,因此我不能将其作为任何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数据,这意味着该数据也应作为回调参数传递。

10-06 05:04