REACT:将有状态对象连接到数组

时间:2018-03-27 19:55:50

标签: javascript html reactjs ecmascript-6

我正在尝试创建一个由输入动态填充的不可变状态数组。但是,我无法创建新状态并将其添加到我的people数组中。这样做的正确方法是什么?下面是该问题的jsfiddle演示的链接。

链接演示http://jsfiddle.net/560fyjnp/1536/

映射并返回附加数组:

appendPerson() {
    let newPerson = {
      name: '',
      age: '',
      school: ''
    };

    this.setState((prevState) => ({
      people: prevState.people.concat([newPerson])
    }));
  }

处理来自输入的更改:

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

示例输入:

Name: <input name="name" value={person.name} onChange={this.props.handleChange} />

映射状态并显示有状态字符串:

    {this.state.people.map((person, index) =>
    <div key={index}>
     Name: {person.name}<br />
     Age: {person.age}<br />
     School: {person.school}
     <hr/>
    </div>
    )}

3 个答案:

答案 0 :(得分:2)

Working JSFiddle Here

您需要更新handleChange函数以接受将作为参数传入的索引。您应该bind Inputs中的更改处理程序传入索引:

  handleChange(index, e) {
    // Make a shallow clone of your state array
    const people = [...this.state.people];
    // Update the object at the passed in index with the property name and value
    people[index] = {...people[index], [e.target.name]: e.target.value};
    this.setState({
        people
    });
  }

完整示例:

class Inputs extends React.Component {
  constructor(props) {
    super(props);
    this.state = {}
  }

  render() {
    return (
      <div>
        {this.props.people.map((person, index) =>
            <div key={index}>
          Name: <input name="name" value={person.name} onChange={this.props.handleChange.bind(this, index)} /><br/>
          Age: <input name="age" value={person.age} onChange={this.props.handleChange.bind(this, index)} /><br/>
          School: <input name="school" value={person.school} onChange={this.props.handleChange.bind(this, index)} />
            <hr />
          </div>
         )}
         <button onClick={ this.props.appendPerson }>Add Another Person</button>
      </div>
    );
  }
}

class People extends React.Component {
    constructor(props) {
    super(props);

    this.state = {
      people: [{
        name: 'Jerry',
        age: '20',
        school: 'Fun University'
      }]
    }

      this.handleChange = this.handleChange.bind(this);
      this.appendPerson = this.appendPerson.bind(this);
  }


  handleChange(index, e) {
    const people = [...this.state.people];
    people[index] = {...people[index], [e.target.name]: e.target.value};
    this.setState({
        people
    });
  }

  appendPerson() {
    let newPerson = {
      name: '',
      age: '',
      school: ''
    };

    //this.setState({ people: this.state.people.concat([newPerson])});
    this.setState((prevState) => ({
      people: prevState.people.concat([newPerson])
    }));
  }

  render() {
    return (
      <div>
        <h1>Add Person:</h1>
        <Inputs
          people={this.state.people}
          appendPerson={this.appendPerson}
          handleChange={this.handleChange}
        />

        <h1>People:</h1>
        {this.state.people.map((person, index) =>
        <div key={index}>
         Name: {person.name}<br />
         Age: {person.age}<br />
         School: {person.school}
         <hr/>
        </div>
        )}
      </div>
    );
  }
}

ReactDOM.render(
  <People/>,
  document.getElementById('container')
);

答案 1 :(得分:1)

您必须将索引传递给handleChange。小提琴:http://jsfiddle.net/560fyjnp/1551/

class Inputs extends React.Component {
  constructor(props) {
    super(props);
    this.state = {}
  }

  render() {
    return (
      <div>
        {this.props.people.map((person, index) =>
            <div key={index}>
          Name: <input name="name" data-index={index} value={person.name} onChange={this.props.handleChange} /><br/>
          Age: <input name="age" data-index={index} value={person.age} onChange={this.props.handleChange} /><br/>
          School: <input name="school" data-index={index} value={person.school} onChange={this.props.handleChange} />
            <hr />
          </div>
         )}
         <button onClick={ this.props.appendPerson }>Add Another Person</button>
      </div>
    );
  }
}

class People extends React.Component {
    constructor(props) {
    super(props);

    this.state = {
      people: [{
        name: 'Jerry',
        age: '20',
        school: 'Fun University'
      }]
    }

      this.handleChange = this.handleChange.bind(this);
      this.appendPerson = this.appendPerson.bind(this);
  }


  handleChange(e) {
    this.setState((prevState)=>{
        prevState.people[parseInt(e.target.getAttribute('data-index'))][e.target.name]= e.target.value;
      return prevState;
    })
  }

  appendPerson() {
    let newPerson = {
      name: '',
      age: '',
      school: ''
    };

    //this.setState({ people: this.state.people.concat([newPerson])});
    this.setState((prevState) => ({
      people: prevState.people.concat([newPerson])
    }));
  }

  render() {
    return (
      <div>
        <h1>Add Person:</h1>
        <Inputs
          people={this.state.people}
          appendPerson={this.appendPerson}
          handleChange={this.handleChange}
        />

        <h1>People:</h1>
        {this.state.people.map((person, index) =>
        <div key={index}>
         Name: {person.name}<br />
         Age: {person.age}<br />
         School: {person.school}
         <hr/>
        </div>
        )}
      </div>
    );
  }
}

ReactDOM.render(
  <People/>,
  document.getElementById('container')
);

答案 2 :(得分:1)

您需要稍微更改代码才能使其正常工作。

查看我的解决方案。 JSFiddle demo

以下是input元素中的onChange函数应该如何。

<input name="name" value={person.name} onChange={({ target }) => this.props.handleChange(index, target.name, target.value)} />

然后有handleChange功能。

handleChange(peopleIndex, name, value) {
    this.setState(prevState => {
      const editedPeople = prevState.people[peopleIndex];
      editedPeople[name] = value;

      return {
        people: [
          ...prevState.people.slice(0, peopleIndex),
          editedPeople,
          ...prevState.people.slice(peopleIndex + 1)
        ]
      };
    });
  }

你有它。与没有data-*属性的输入链接的独立数据结构。

希望这有帮助。