首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何避免添加现场变更处理方法和其他反应形式的样板?

如何避免添加现场变更处理方法和其他反应形式的样板?
EN

Stack Overflow用户
提问于 2017-07-04 16:04:50
回答 3查看 64关注 0票数 4

我有一个基于反应的表单,其中包含超过10个字段,对于这10个字段,(受控组件)

这些input字段大多数都是text类型的,但其他类型的字段将在稍后添加。

问题是,我需要编写10更改处理程序,以便它们正确设置状态,然后在构造函数中为每个处理程序添加方法绑定。

我对此反应很新,可能不知道正确的方法和技巧。

请指导我如何改进我目前的代码结构,避免编写锅炉板和重复错误的代码。

我现在的注册内容如下-

代码语言:javascript
运行
复制
export default class Register extends Component {

    constructor(props){
        super(props);
        this.state = {
            regName              : '',
            regAdd1              : '',
            regAdd2              : '',
            regState             : '',
            regZipCode           : '',
            regCity              : '',
            regPhone             : ''
        };
        // add bindings .... ugh..
        this.changeRegAdd1 = this.changeRegAdd1.bind(this);
        this.changeRegAdd2 = this.changeRegAdd2.bind(this);
        //Similary binding for other handlers...
    }

    // add individual field change handlers ... ugh...
    changeRegName(e) {
        this.setState({regName:e.target.value});
    }

    changeRegAdd1(e) {
        this.setState({regAdd1:e.target.value});
    }

    changeRegAdd2(e) {
        this.setState({regAdd2:e.target.value});
    }

    changeRegState(e) {
        this.setState({regState:e.target.value});
    }


    // Similary for other change handler ....

    handleSubmit(e) {
        e.preventDefault();
        // validate then do other stuff
    }

    render(){

        let registrationComp = (
                <div className="row">
                    <div className="col-md-12">
                        <h3>Registration Form</h3>
                        <fieldset>
                              <div className="form-group">
                                <div className="col-xs-12">
                                    <label htmlFor="regName">Name</label>
                                    <input type="text" placeholder="Name"
                                        onChange={this.changeregName} value = {this.state.regName} className="form-control" required autofocus/>
                                </div>
                              </div>

                              <div className="form-group">
                                <div className="col-xs-12">
                                    <label htmlFor="regAdd1">Address Line1</label>

                                    <input
                                        type        = "text"
                                        placeholder = "Address Line1"
                                        onChange    = {this.changeregAdd1}
                                        value       = {this.state.regAdd1}
                                        className   = "form-control"
                                        required
                                        autofocus
                                    />

                                    <input
                                        type        = "text"
                                        placeholder = "Address Line2"
                                        onChange    = {this.changeregAdd2}
                                        value       = {this.state.regAdd2}
                                        className   = "form-control"
                                        required
                                        autofocus
                                    />
                                </div>
                              </div>

                              <div className="form-group">
                                <div className="col-xs-6">
                                    <label htmlFor="regState">State</label>
                                    <input
                                        type        = "text"
                                        placeholder = "State"
                                        onChange    = {this.changeregState}
                                        value       = {this.state.regState}
                                        className   = "form-control"
                                        required
                                        autofocus
                                    />
                                </div>
                                <div className="col-xs-6">
                                    <label htmlFor="regZipCode">Zip Code</label>
                                    <input
                                        type        = "text"
                                        placeholder = "Zip Code"
                                        onChange    = {this.changeregZipCode}
                                        value       = {this.state.regZipCode}
                                        className   = "form-control"
                                        required
                                        autofocus
                                    />
                                </div>
                              </div>

                              <div className="form-group">
                                <div className="col-xs-12">
                                    <label htmlFor="regCity">City</label>
                                    <input
                                        type        = "text"
                                        placeholder = "City"
                                        title       = "City"
                                        onChange    = {this.changeregCity}
                                        value       = {this.state.regCity}
                                        className   = "form-control"
                                        required
                                        autofocus
                                    />
                                </div>
                              </div>
                              {/* other form fields */}
                          </fieldset>
                      </div>
                    </div>
            );

            return  registrationComp;
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-04 16:06:53

还有很多其他的方法,我可能不知道。

但是,我更喜欢对某些类型的公共字段(如<input type of text /> )进行公共方法中的更改处理。

这是一个样本输入字段-

代码语言:javascript
运行
复制
  <input
      onChange    = {this.onChange}
      value       = {this.state.firstName}
      type        = "text"
      name        = {"firstName"}
  />

我将状态的字段名和输入的" name "属性保持相同。之后,我为所有这些字段编写了一个公共更改处理程序

只需在更改处理程序中编写一行。

代码语言:javascript
运行
复制
onChange(e) {
    this.setState({[e.target.name]: e.target.value});
}

我使用es6的动态属性设置from string作为属性名。

代码语言:javascript
运行
复制
{ ["propName] : propValue }.

为了避免为react组件中的方法编写手动绑定,您可以遵循以下两种方法-

  1. 使用es6箭头函数
  2. 黑客攻击(我不知道这种方法是快速的还是慢的,但它有效:)

在组件中创建这样的方法。

代码语言:javascript
运行
复制
_bind(...methods) {
  methods.forEach( (method) => this[method] = this[method].bind(this) );
 }

使用_bind绑定您的方法。

代码语言:javascript
运行
复制
constructor(props){
    super(props);
    this.state = {
        regName              : '',
        regAdd1              : '',
        regAdd2              : '',
        regState             : '',
        regZipCode           : '',
        regCity              : '',
        regPhone             : ''
    };
    // add bindings .... ugh..
    //this.changeRegAdd1 = this.changeRegAdd1.bind(this);
    //this.changeRegAdd2 = this.changeRegAdd2.bind(this);
    //Similary binding for other handlers...

    this._bind(
        'changeRegName',
        'changeReg1'    , 'changeRegAdd2'
        // and so on.
    );


}

编辑:

添加验证-

  1. 编写一个可以迭代状态键并检查状态是否为空的方法。
  2. 如果任何输入字段为空,则收集有关该输入的详细信息并标记所需的内容。
  3. 设置状态以指示窗体有错误。在state的error对象中可以找到特定的错误细节。 validateInput() { let错误= {};Object.keys(this.state) .forEach((stateKey) => { isEmpty(this.statestateKey)?(errorsstateKey = \*required ):null;});返回{错误,isValid :isEmptyObj(错误) };} isFormValid() { const { errors,isValid }= this.validateInput();if (!isValid) { this.setState({错误});}返回isValid;} onSubmit(e) { e.preventDefault();this.setState({errors:{}});if (this.isFormValid()) { //执行表单提交}}

我已经习惯了实用的方法isEmptyisEmptyObj。他们只是检查对象是空的还是未定义的,或者字段是空的。

我希望这能帮到你。

票数 5
EN

Stack Overflow用户

发布于 2017-07-04 16:34:44

您可以创建一个高阶组件来处理其中的许多问题。如果你愿意的话,剩馀形式有一个很好的模式,你可以模仿它。

从本质上讲,您将得到类似于以下内容的结果(我根本没有测试过这一点,但它应该运行得很好):

代码语言:javascript
运行
复制
export class Field extends Component {
  handleChange = (event) => this.props.onChange(this.props.name, event.target.value)

  render() {
    const InputComponent = this.props.component
    const value = this.props.value || ''

    return (
      <InputComponent
        {...this.props}
        onChange={this.handleChange}
        value={value}
      />
  }
}

export default function createForm(WrappedComponent) {
  class Form extends Component {
    constructor() {
      super()

      this.state = this.props.initialValues || {}
      this.handleChange = this.handleChange.bind(this)
    }

    handleChange(name, value) {
      this.setState({
        [name]: value,
      })
    }

    render() {
      return (
        <WrappedComponent
          {...this.state}
          {...this.props}
          // pass anything you want to add here
          onChange={this.handleChange}
          values={this.state}
        />
      )
    }
  }

  return Form
}

然后,您可以根据需要增强这个组件(添加焦点、模糊、提交处理程序等)。你可以用这样的方法:

代码语言:javascript
运行
复制
import createForm, { Field } from './createForm'

// simplified Registration component
export class Registration extends Component {
  render() {
    return (
      <form>
        <Field
          component="input"
          name="name"
          onChange={this.props.onChange}
          type="text"
          value={this.props.values.name}
        />
      </form> 
    )
  }
}

export default createForm(Registration)

您可能会疯狂地进入上下文,这样您就不必手动传递值和函数,但我至少会远离它,直到您更加熟悉React为止。

另外,如果您不想手动绑定函数,那么如果使用babel,可以使用类属性变换。然后,Form组件的外观将如下所示:

代码语言:javascript
运行
复制
class Form extends Component {
  state = this.props.initialValues || {}

  handleChange = (name, value) => this.setState({
    [name]: value,
  })

  render() {
    return (
      <WrappedComponent
        {...this.state}
        {...this.props}
        onChange={this.handleChange}
        values={this.state}
      />
    )
  }
}
票数 2
EN

Stack Overflow用户

发布于 2017-07-04 19:44:13

看看它是如何在NeoForm中完成的

  • 数据状态直接映射到表单字段。
  • 一个用于整个表单的onChange处理程序
  • 每个字段(例如onBlur)和表单(例如onSubmit)验证
  • 普通对象和不可变状态帮助器
  • 易于与Redux或任何其他状态管理解决方案集成

它在内部使用context,非常小且模块化的源代码很容易理解。

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

https://stackoverflow.com/questions/44910295

复制
相关文章

相似问题

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