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

IT技术 javascript reactjs jsx
2021-02-06 14:05:55

好奇解决这个问题的正确方法是什么:

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 函数来处理每个不同的输入,但这不是很好。同样,您可以仅为单个输入创建一个组件,但我想看看是否有办法做到这一点。

6个回答

我建议坚持使用标准的 HTML 属性,例如Elementsname上的input属性来识别您的输入。此外,您不需要在 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'));
使用 bind 是更好的方法。如果将 onChange 处理程序附加到没有 name 属性的元素(例如 div),则此方法不起作用。
2021-03-18 14:05:55
我最初试图这样做,但是 setState({e.target.name... 不起作用 - 这是一个语法错误。您必须使用 obj[e.target.name] 和 setState 创建一个临时对象。这种工作,但状态对象更新似乎有某种延迟。
2021-03-20 14:05:55
在这种情况下,@ericgrosse bind 并不是更好,因为您正在创建许多不必要的功能。此外,如果需要,您可以在不同类型的元素上使用数据属性或其他内容
2021-04-04 14:05:55
“某种延迟”是在 requestAnimationFrame 期间更新 setState(我假设),因此请忽略该评论
2021-04-13 14:05:55
@T3db0t 这个 ES6 语法有效: this.setState({ [e.target.name]: e.target.value });
2021-04-14 14:05:55

您可以使用该.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渲染时进行了计算,因为这是推荐的做法。)

我认为还有一点很重要,setState 的本质是,不能在 handChange 函数中检索当前状态,而是使用 this.state.input1 来检索之前的状态,例如。一个正确的方法是创建一个回调,例如this.setState(change, function () { console.log(this.state.input1); );参考:stackoverflow.com/questions/30782948/...
2021-03-15 14:05:55
如果您更改handleChangeto 的实现,handleChange(name) { return event => this.setState({name: event.target.value}); }您可以传递“相同”函数(不会像使用.bind()Then那样创建新函数,您可以传递这样的函数:this.handleChange("input1")
2021-03-16 14:05:55
只是一个this.handleChange.bind(...)创建新功能的快速提醒如果您使用shouldComponentUpdatewithPureRenderMixin或类似的东西,它会坏掉。当单个值更改时,所有输入组件都将重新呈现。
2021-03-18 14:05:55
嗨@flatjaf 这是一种错误的方法,因为它在渲染时失去了功能
2021-03-24 14:05:55
这个答案已经过时了。有人请编辑它。我不再使用 React,所以我不确定现在什么是正确的答案。
2021-04-11 14:05:55

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

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

已弃用的解决方案

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!
2021-04-05 14:05:55
请注意,此解决方案已弃用
2021-04-08 14:05:55

你也可以这样做:

...
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 开发者工具。它为称为 input 的变量/对象创建和赋值,而不是 input1 / input2
2021-04-01 14:05:55
@Gaurravs 是的,你是对的。我需要添加[]围绕input成的setState。这使得属性动态分配
2021-04-14 14:05:55