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


141

好奇解决此问题的正确方法是:

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'));

显然,您可以创建单独的handleChange函数来处理每个不同的输入,但这不是很好。同样,您可以为单个输入创建一个组件,但是我想看看是否有办法做到这一点。

Answers:


162

我建议坚持name使用input元素上的标准HTML属性来标识您的输入。另外,您不需要将“总计”作为单独的值保留在状态中,因为可以通过在状态中添加其他值来构成“总计”:

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'));

3
我最初尝试这样做,但是setState({e.target.name ...不起作用-这是一个语法错误。您必须使用obj [e.target.name]和setState来创建一个临时对象。这种工作,但状态对象更新似乎有些延迟
T3db0t 2014年

1
“某种延迟”是在requestAnimationFrame(我假设)期间更新setState的,所以请忽略该备注
T3db0t 2014年

24
@ T3db0t这ES6语法著作this.setState({ [e.target.name]: e.target.value });
XåpplI'-I0llwlg'I -

2
使用绑定是更好的方法。如果将onChange处理程序附加到没有名称属性的元素(例如div),则此方法不起作用。
ericgrosse

3
在这种情况下,@ ericgrosse绑定并不更好,因为您正在创建许多不必要的功能。同样,如果需要,您可以在其他种类的元素上使用data-attribute属性或其他内容
aw04

106

您可以使用该.bind方法来预构建该handleChange方法的参数。就像这样:

  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'));

(我也total建议在渲染时进行计算,因为这是推荐的操作。)


13
快速提醒一下,它this.handleChange.bind(...)会创建一个新功能。如果您使用shouldComponentUpdatewith PureRenderMixin或类似的东西,它将损坏。当单个值更改时,所有输入组件都将重新呈现。
zemirco

5
如果您将的实现更改为handleChange,则handleChange(name) { return event => this.setState({name: event.target.value}); }可以传递“相同”函数(不会通过使用.bind()Then 来创建新函数,则可以传递此类函数:this.handleChange("input1")
Andreyco

1
我认为值得一提的是setState的性质是,它不能在handChange函数中检索当前状态,而只能使用this.state.input1检索前一个状态。一个适当的方法将是创建一个回调如this.setState(change, function () { console.log(this.state.input1); );参考:stackoverflow.com/questions/30782948/...
查理-格林曼

38

onChange事件冒泡......所以,你可以这样做:

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

而且您的setField方法可能看起来像这样(假设您使用的是ES2015或更高版本:

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

我在几个应用程序中都使用了类似的东西,这非常方便。


11

弃用的解决方案

valueLink/checkedLink已从核心React 中弃用,因为它使某些用户感到困惑。如果您使用最新版本的React,此答案将不起作用。但是,如果您喜欢它,则可以通过创建自己的模型轻松地模拟它Input组件

旧答案内容:

使用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'));

容易吧?

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

您甚至可以实现自己的mixin


为什么我们必须绑定一个onchange来设置状态。毕竟是ReactJS!
Junaid Qadir

请注意,此解决方案已弃用
Philipp'8

6

您也可以这样:

...
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>
    )
}

没有为我工作。看到了React开发人员工具。它的创建和赋值给称为输入的变量/对象,而不是输入1 /输入2
Gaurravs

1
@Gaurravs是的,你是对的。我需要添加[]围绕input成的setState。这使得该物业
得以

4

您可以使用的特殊React属性ref,然后onChange使用ReactgetDOMNode()功能来匹配事件中的真实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>
  ...
}

至少在0.13中,this.refs没有属性首选项。
blub 2015年

2
@usagidon - prev就是我在设置一个名称render()方法
雅努什Kacalak

2
从React v0.14开始,您可以这样做event.target === this.refs.prevfacebook.github.io/react/blog/2015/10/07/...
XåpplI'-I0llwlg'I -

0

@Vigril Disgr4ce

对于多字段表单,使用React的关键功能(组件)是有意义的。

在我的项目中,我创建了TextField组件,这些组件至少具有一个值道具,并且它负责处理输入文本字段的常见行为。这样,您在更新值状态时不必担心跟踪字段名称。

[...]

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} />;
}

[...]

0

您可以input通过创建一个单独的InputField组件来管理单个孩子的价值来跟踪每个孩子的价值input。例如,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} />)
  }
})

现在,input可以在该InputField组件的单独实例中跟踪每个组件的值,而无需在父级状态下创建单独的值来监视每个子组件。


0

我将为这个问题提供非常简单的解决方案。假设我们有两个输入usernamepassword,但是我们希望我们的句柄是简单而通用的,因此我们可以重用它并且不编写样板代码。

一,我们的表格:

                <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。我们想要保存username和的构造函数,password因此我们可以轻松地访问它们:

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

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

III。仅有一个onChange事件的有趣且“通用”的句柄基于此:

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

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


    event.preventDefault();
}

让我解释:

1.检测到更改时onChange(event)称为

2,然后我们得到该字段的名称参数及其值:

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

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

3.基于name参数,我们从构造函数中的状态获取值,并使用以下值对其进行更新:

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

4,这里要注意的关键是字段名称必须与状态中的参数匹配

希望我能以某种方式帮助某人:)


0

您的状态键应与输入字段的名称相同。然后,您可以在handleEvent方法中执行此操作;

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

-1

您好,ssorallen的答案有所改善。您不需要绑定功能,因为您可以在没有输入的情况下访问输入。

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'));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.