首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试在不使用eval()的情况下构建React中的泛型表单组件

尝试在不使用eval()的情况下构建React中的泛型表单组件
EN

Stack Overflow用户
提问于 2019-01-29 10:03:34
回答 1查看 869关注 0票数 2

我目前正试图为我的React应用程序编写一个通用表单组件。我知道那里有很多很棒的图书馆,但在这一点上,它们对我来说似乎都是过头了。

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

我的<BasicForm>组件应该处理表单stateonChangeonBluronSubmit等,还应该处理验证(基于我作为children添加的每个输入类型)。

其动机是,每次需要创建新表单时,我都会感到重复,必须一次又一次地管理输入、验证、onChangesubmit函数的submit

下面是我使用<Basic Form>的代码

BasicForm-Consumer.js

代码语言:javascript
复制
  <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>添加源代码以避免这个问题太长,但基本上它用React.Children.map处理所有输入children,它对每种输入都有验证函数,也有处理更改、模糊、提交等的函数。它还为每个输入字段创建了一个state

问题简介

代码语言:javascript
复制
  <BasicForm
    submitFunction={props.linkEmailAndPassword}
    submitAction={'this.props.submitFunction(this.state.passwordOne)'}
  >

正如您从上面的片段中看到的那样,为了将submitAction从使用者发送到<BasicForm>,我必须将其包装在一个字符串中,因为它引用的是只存在于<BasicForm>中的state。最重要的是,我需要提交的特定state部件是在<BasicForm>之外(在使用者中)定义的。

使用者定义了state的哪个部分或哪些部分应该提交,并且在每一种情况下都是不同的,因此我不能把它作为一个“通用”state名称,任何<BasicForm>都会作为内置的。

因此,我以字符串的形式发送,在<BasicForm>中,我不得不使用最不推荐的eval(),如下所示:

BasicForm.js

代码语言:javascript
复制
  onSubmit(event) {
    event.preventDefault();
    this.validateAllFields();
    eval(this.props.submitAction);
  }

真题

在这种情况下,eval()有多糟糕?通过这样做,我是否将我的应用程序暴露给了“恶意黑客”?我应该以任何方式消毒它,即使它不是用户输入?还有别的办法可以绕开吗?我真的很高兴,因为每次我需要的时候都不用从头开始构建一个表单。现在,我只关注字段和验证需求。耽误您时间,实在对不起!

附加信息

P.S.:这是一个输入组件TextInput的代码。PasswordInput就像这样。唯一的区别是type='password'

TextInput.js

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-29 12:02:30

Eval几乎从不受欢迎,因为它会带来安全风险、性能损失,并表明存在设计问题。

这取决于它的使用是否存在安全风险。如果评估表达式可能直接或间接包含用户输入,则存在安全风险。否则,只适用于性能和设计方面的问题。

在这种情况下,这意味着BasicForm未能向父组件提供合理的API,因此最终得到了eval。正确的方法是回调。

由于父组件一般不应该知道BasicForm实现细节并访问它的实例,所以BasicForm this不应该在回调中可用。BasicForm道具已经在回调中可用--它们是在父组件中传递的。因为它已知BasicForm state包含来自其子输入的值,所以它应该可以在回调中使用。

因此,BasicForm回调看起来可能是:

代码语言:javascript
复制
  <BasicForm
    onSubmit={state => props.linkEmailAndPassword(state.passwordOne)}}

  ...

  onSubmit(event) {
    event.preventDefault();
    this.validateAllFields();
    this.props.onSubmit(this.state);
  }

如果需要onSubmit回调来访问除其状态之外的任何BasicForm数据,这意味着该数据也应作为回调参数传递。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54418448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档