【问题标题】:React: Binding array to dynamically added fieldsReact:将数组绑定到动态添加的字段
【发布时间】:2016-03-01 18:53:51
【问题描述】:

假设我有一个带有状态级数组的类

ElementsClass = React.createClass({
    getInitialState: function() {
      return {
          elements: []
      }
    },
    addElement: function() {
        var element = {
            name: ""
        };
    },
    render() {
        return (
            {this.state.elements.map(function (element, i) {
                    return <input value={element.name} />
                }
            )}
        )
}

我的想法是我可以动态添加到元素数组并出现一个新的输入字段。

如何绑定数据,以便能够更改输入字段中的值并使其自动反映在元素数组中的正确元素中?

【问题讨论】:

    标签: javascript reactjs jsx


    【解决方案1】:

    要将输入与状态数组动态同步,您可以使用 react-catalyst 包中的 linkState。使用 npm 安装后,您可以通过以下方式使用它:

     //need to import
    import Catalyst from 'react-catalyst'; 
    
    ElementsClass = React.createClass({
        // mixin the linkedstate component
        mixins : [Catalyst.LinkedStateMixin],       
    
        getInitialState: function() {
          return {
              elements: []
          }
        },
        addElement: function() {
            var element = {
                name: ""
            };
    
            //add to elements array
            this.state.elements.push(element);
    
            //let react know to rerender necessary parts
            this.setState({
                elements : this.state.elements
            });
        },
        render() {
            return (
                {this.state.elements.map(function (element, i) {
                        //use the linkState method
                        return <input valueLink={this.linkState('elements.'+i+'.name')} />
                    }
                )}
            )
    }
    

    我们需要 react-catalyst 包的原因是 React 的 valueLink 将仅链接顶级状态项,在您的情况下为 elements。显然这并不是特别有用,但幸运的是,这是一个相当容易解决的问题。

    注意:对于像元素输入这样的迭代项,您需要提供唯一键。类似于以下内容(可能需要修改为更具体):

    {this.state.elements.map(function (element, i) {
            //use the linkState method
            return <input valueLink={this.linkState('elements.'+i+'.name')} key={'elinput' + i} />
        }
    )}
    

    这对您的应用没有任何外部影响,主要是帮助在内部对目标元素做出反应。

    【讨论】:

    • 对不起,我认为我没有完全澄清这个问题。将value={element.name}添加到输入字段时,无法修改输入字段。如何添加正确定位元素数组中相关条目的 onChange 方法
    • @Pram 啊,我完全误解了。这实际上有点棘手。你必须使用valueLink 而不是value 但是 React 只允许顶级状态值。我会更新我的答案,但你需要一个像 react-catalyst 这样的库来进行双向绑定。
    【解决方案2】:

    如果你只想用 ES5 和 React 来做这件事,一个解决方案是这样的:

    var ElementsClass = React.createClass({
    
    getInitialState: function() {
      return {
          elements: []
      }
    },
    createElement: function(){
      var element = {
        name: ''
      };
      this.setState({elements: this.state.elements.concat(element)});
    },
    updateElement: function(pos, event) {
        var value = event.target.value;
        var updatedElements = this.state.elements.map(function(element, i){
          if (i === pos){
            return {name: value};
          }
          return element;
        });
        this.setState({elements: updatedElements});
    },
    render: function() {
        console.log(this.state.elements);
        return (
          <div>
            {this.state.elements.map(function (element, i) {
               var boundClick = this.updateElement.bind(this, i);
               return <input key={i} onKeyUp={boundClick}/>
            }.bind(this))}
            <button onClick={this.createElement}>Add Element</button>
          </div>
        )
    }
    });
    
    React.render(<ElementsClass />, document.getElementById('app'));
    

    您希望将组件状态视为不可变的,因此您不想调用诸如推送元素之类的变异方法。

    【讨论】:

    • 这个答案是如何挽救我的生命的!谢谢
    【解决方案3】:

    使用自定义链接包可以轻松处理这些情况。

    State and Forms in React, Part 3: Handling the Complex State

    import Link from 'valuelink';
    
    // linked inputs will be deprecated, thus we need to use custom wrappers 
    import { Input } from 'valueLink/tags.jsx'
    
    const ElementsClass = React.createClass({
        getInitialState: function() {
          return {
              elements: []
          }
        },
    
        render() {
            // Take link to the element
            const elementsLink = Link.state( this, 'elements' );
    
            return (
                <div>
                    { elementsLink.map( ( elementLink, i ) => (
                         <Input key={ i } valueLink={ elementLink.at( 'name' ) } />  
                    ))}
    
                    <button onClick={ elementsLink.push({ name : '' })}>
                        Add Elements
                    </button>
                </div>
            );
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-09
      • 1970-01-01
      • 2019-03-03
      相关资源
      最近更新 更多