4

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

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

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

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

4

3 回答 3

2

要将您的输入与您的状态数组动态同步,您可以使用linkStatereact-catalyst包中调用的东西。使用 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包的原因是,在你的情况下,原生 ReactvalueLink只会链接顶级状态项elements。显然,这并不是特别有用,但值得庆幸的是,这是一个相当容易解决的问题。

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

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

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

于 2016-03-01T19:03:39.663 回答
1

如果你只想用 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'));

您希望将组件状态视为不可变的,因此您不想调用像 push on 元素这样的变异方法。

于 2016-03-01T20:12:36.240 回答
0

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

React 中的状态和表单,第 3 部分:处理复杂状态

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>
        );
    }
});
于 2016-06-02T18:16:32.560 回答