简体   繁体   English

React.js:使用一个 onChange 处理程序识别不同的输入

[英]React.js: Identifying different inputs with one onChange handler

Curious what the right way to approach this is:好奇解决这个问题的正确方法是什么:

var Hello = React.createClass({
getInitialState: function() {
    return {total: 0, input1:0, input2:0};
},
render: function() {
    return (
        <div>{this.state.total}<br/>
            <input type="text" value={this.state.input1} onChange={this.handleChange} />
            <input type="text" value={this.state.input2} onChange={this.handleChange} />
        </div>
    );
},
handleChange: function(e){
    this.setState({ ??? : e.target.value});
    t = this.state.input1 + this.state.input2;
    this.setState({total: t});
}
});

React.renderComponent(<Hello />, document.getElementById('content'));

Obviously you could create separate handleChange functions to handle each different input, but that's not very nice.显然,您可以创建单独的 handleChange 函数来处理每个不同的输入,但这不是很好。 Similarly you could create a component just for an individual input, but I wanted to see if there's a way to do it like this.同样,您可以仅为单个输入创建一个组件,但我想看看是否有办法做到这一点。

I suggest sticking to standard HTML attributes like name on input Elements to identify your inputs.我建议坚持使用标准的 HTML 属性,例如input元素上的name来标识您的输入。 Also, you don't need to keep "total" as a separate value in state because it is composable by adding other values in your state:此外,您不需要在 state 中将“total”作为单独的值保留,因为它可以通过在您的 state 中添加其他值来组合:

var Hello = React.createClass({
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },
    render: function() {
        const total = this.state.input1 + this.state.input2;

        return (
            <div>{total}<br/>
                <input type="text" value={this.state.input1} name="input1" onChange={this.handleChange} />
                <input type="text" value={this.state.input2} name="input2" onChange={this.handleChange} />
            </div>
        );
    },
    handleChange: function(e) {
        this.setState({[e.target.name]: e.target.value});
    }
});

React.renderComponent(<Hello />, document.getElementById('content'));

You can use the .bind method to pre-build the parameters to the handleChange method.您可以使用.bind方法预先构建handleChange方法的参数。 It would be something like:它会是这样的:

  var Hello = React.createClass({
    getInitialState: function() {
        return {input1:0, 
                input2:0};
    },
    render: function() {
      var total = this.state.input1 + this.state.input2;
      return (
        <div>{total}<br/>
          <input type="text" value={this.state.input1} 
                             onChange={this.handleChange.bind(this, 'input1')} />
          <input type="text" value={this.state.input2} 
                             onChange={this.handleChange.bind(this, 'input2')} />
        </div>
      );
    },
    handleChange: function (name, e) {
      var change = {};
      change[name] = e.target.value;
      this.setState(change);
    }
  });

  React.renderComponent(<Hello />, document.getElementById('content'));

(I also made total be computed at render time, as it is the recommended thing to do.) (我还在渲染时计算了total ,因为这是推荐的做法。)

The onChange event bubbles... So you can do something like this: onChange事件冒泡......所以你可以做这样的事情:

// A sample form
render () {
  <form onChange={setField}>
    <input name="input1" />
    <input name="input2" />
  </form>
}

And your setField method might look like this (assuming you're using ES2015 or later:您的 setField 方法可能如下所示(假设您使用的是 ES2015 或更高版本:

setField (e) {
  this.setState({[e.target.name]: e.target.value})
}

I use something similar to this in several apps, and it's pretty handy.我在几个应用程序中使用了类似的东西,它非常方便。

Deprecated solution已弃用的解决方案

valueLink/checkedLink are deprecated from core React, because it is confusing some users. valueLink/checkedLink从核心 React 中被弃用,因为它让一些用户感到困惑。 This answer won't work if you use a recent version of React.如果您使用最新版本的 React,此答案将不起作用。 But if you like it, you can easily emulate it by creating your own Input component但是如果你喜欢它,你可以通过创建你自己的Input组件来轻松地模仿它

Old answer content:旧答案内容:

What you want to achieve can be much more easily achieved using the 2-way data binding helpers of React.使用 React 的 2 路数据绑定助手可以更轻松地实现您想要实现的目标。

var Hello = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },

    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
            <div>{total}<br/>
                <input type="text" valueLink={this.linkState('input1')} />;
                <input type="text" valueLink={this.linkState('input2')} />;
            </div>
        );
    }

});

React.renderComponent(<Hello />, document.getElementById('content'));

Easy right?容易吧?

http://facebook.github.io/react/docs/two-way-binding-helpers.html http://facebook.github.io/react/docs/two-way-binding-helpers.html

You can even implement your own mixin你甚至可以实现你自己的 mixin

You can also do it like this:你也可以这样做:

...
constructor() {
    super();
    this.state = { input1: 0, input2: 0 };
    this.handleChange = this.handleChange.bind(this);
}

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

render() {
    const total = this.state.input1 + this.state.input2;
    return (
        <div>
            {total}<br />
            <input type="text" onChange={e => this.handleChange('input1', e.target.value)} />
            <input type="text" onChange={e => this.handleChange('input2', e.target.value)} />
        </div>
    )
}

You can use a special React attribute called ref and then match the real DOM nodes in the onChange event using React 's getDOMNode() function:您可以使用称为ref的特殊React属性,然后使用ReactgetDOMNode()函数匹配onChange事件中的真实 DOM 节点:

handleClick: function(event) {
  if (event.target === this.refs.prev.getDOMNode()) {
    ...
  }
}

render: function() {
  ...
  <button ref="prev" onClick={this.handleClick}>Previous question</button>
  <button ref="next" onClick={this.handleClick}>Next question</button>
  ...
}

If anyone looking for Functional Component Example,如果有人在寻找功能组件示例,

import React, { useState } from "react";

export default function Exapmle() {

const [userState, setUserState] = useState({
  firstName: "",
  lastName: ""
})

const handleChange = (e)=>{
   const value = e.target.value;
   setUserState({
    ...userState,
    [e.target.name]: value
   });
}

return (
  <form>

    <label>
      First name
      <input type="text" name="firstName" value={userState.firstName}
        onChange={handleChange}
      />
    </label>

    <label>
      Last name
      <input type="text" name="lastName" value={userState.lastName}
        onChange={handleChange}
      />
    </label>

  </form>
 );
}

@Vigril Disgr4ce @Vigril Disgr4ce

When it comes to multi field forms, it makes sense to use React's key feature: components.当涉及到多字段表单时,使用 React 的关键特性:组件是有意义的。

In my projects, I create TextField components, that take a value prop at minimum, and it takes care of handling common behaviors of an input text field.在我的项目中,我创建了 TextField 组件,这些组件至少带有一个 value 属性,它负责处理输入文本字段的常见行为。 This way you don't have to worry about keeping track of field names when updating the value state.这样您就不必担心在更新值状态时跟踪字段名称。

[...]

handleChange: function(event) {
  this.setState({value: event.target.value});
},
render: function() {
  var value = this.state.value;
  return <input type="text" value={value} onChange={this.handleChange} />;
}

[...]

You can track the value of each child input by creating a separate InputField component that manages the value of a single input .您可以通过创建一个单独的InputField组件来管理单个input的值,从而跟踪每个子input的值。 For example the InputField could be:例如InputField可以是:

var InputField = React.createClass({
  getInitialState: function () {
    return({text: this.props.text})
  },
  onChangeHandler: function (event) {
     this.setState({text: event.target.value})
  }, 
  render: function () {
    return (<input onChange={this.onChangeHandler} value={this.state.text} />)
  }
})

Now the value of each input can be tracked within a separate instance of this InputField component without creating separate values in the parent's state to monitor each child component.现在,可以在此InputField组件的单独实例中跟踪每个input的值,而无需在父组件的状态中创建单独的值来监视每个子组件。

I will provide really simple solution to the problem.我将为这个问题提供非常简单的解决方案。 Suppose we have two inputs username and password ,but we want our handle to be easy and generic ,so we can reuse it and don't write boilerplate code.假设我们有两个输入usernamepassword ,但我们希望我们的句柄简单通用,这样我们就可以重用它并且不编写样板代码。

I.Our form:一、我们的形式:

                <form>
                    <input type="text" name = "username" onChange={this.onChange} value={this.state.username}/>
                    <input type="text" name = "password" onChange={this.onChange} value={this.state.password}/>
                    <br></br>
                    <button type="submit">Submit</button>
                </form>

II.Our constructor ,which we want to save our username and password ,so we can access them easily: II.我们的构造函数,我们想保存我们的usernamepassword ,以便我们可以轻松访问它们:

constructor(props) {
    super(props);
    this.state = {
        username: '',
        password: ''
    };

    this.onSubmit = this.onSubmit.bind(this);
    this.onChange = this.onChange.bind(this);
}

III.The interesting and "generic" handle with only one onChange event is based on this: III.只有一个onChange事件的有趣且“通用”的句柄基于此:

onChange(event) {
    let inputName = event.target.name;
    let value = event.target.value;

    this.setState({[inputName]:value});


    event.preventDefault();
}

Let me explain:让我解释:

1.When a change is detected the onChange(event) is called 1.当检测到变化时,调用onChange(event)

2.Then we get the name parameter of the field and its value: 2.然后我们获取字段的名称参数及其值:

let inputName = event.target.name; ex: username

let value = event.target.value; ex: itsgosho

3.Based on the name parameter we get our value from the state in the constructor and update it with the value: 3.基于 name 参数,我们从构造函数中的状态中获取我们的值并使用该值更新它:

this.state['username'] = 'itsgosho'

4.The key to note here is that the name of the field must match with our parameter in the state 4.这里要注意的关键是field的名字必须和我们在state中的参数相匹配

Hope I helped someone somehow :)希望我以某种方式帮助了某人:)

The key of your state should be the same as the name of your input field.您状态的键应该与输入字段的名称相同。 Then you can do this in the handleEvent method;然后你可以在 handleEvent 方法中做到这一点;

this.setState({
        [event.target.name]: event.target.value
});

state object状态对象

const [values, setValues] = useState({
    email: "",
    password: "",
  });

function that change state改变状态的函数

const handleChange = name => event => {
    setValues({ ...values, [name]: event.target.value });
 };

call above function on onchange of input with "name"使用“名称”更改输入时调用上述函数

<input 
onChange={handleChange("email")} 
value={email}
className="form-control"
type="email"
       />

Hi have improved ssorallen answer.嗨,已经改进了ssorallen 的答案。 You don't need to bind function because you can access to the input without it.您不需要绑定函数,因为您可以在没有它的情况下访问输入。

var Hello = React.createClass({
    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
             <div>{total}<br/>
                  <input type="text" 
                    value={this.state.input1}
                    id="input1"  
                    onChange={this.handleChange} />
                 <input type="text" 
                    value={this.state.input2}
                    id="input2" 
                    onChange={this.handleChange} />
            </div>
       );
   },
   handleChange: function (name, value) {
       var change = {};
       change[name] = value;
       this.setState(change);
   }
});

React.renderComponent(<Hello />, document.getElementById('content'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM