当父状态更新时,反应父组件重置子组件状态

时间:2018-10-05 19:04:58

标签: javascript reactjs

我有一个名为ToDoLists的父组件,其中包含一个输入,并允许您输入一个新的待办事项列表名称。该组件映射到处于组件状态的列表数组,以创建不同的List组件。

列表组件使您可以添加待办事项。 例如:早上例行清单,含早餐,淋浴,剃须待办事项。

我可以获取ToDoLists组件来创建新的List组件。但是,当我在List组件中添加待办事项时,在父组件的输入中重新键入状态似乎会擦除子组件的状态。

React刚起步,所以我不确定这是否是尝试执行此操作的正确方法。这是因为添加新列表时需要通过prevState吗?在此先感谢您朝正确的方向前进。

ToDoLists组件

import React, { Component } from 'react';
import '../App.css';
import List from './list.js';

class ToDoLists extends Component {
  constructor(props){
    super(props)
    this.state = {
      term: '',
      list: []
    };
  }
  onChange = (event) => {
    this.setState({term: event.target.value});
  }
  onSubmit = (event) => {
    event.preventDefault()
    this.setState({
      term: '',
      list: [...this.state.items, this.state.term]
    })
  }

  render() {
    const generateKey = (x) => {
      return `${x}_${new Date().getTime()}`
    };

    return(
      <div>
        <h3>ToDo Lists Component</h3>
          <form onSubmit={this.onSubmit}>
            <input placeholder='Add A New List' value={this.state.term} onChange={this.onChange}/>
            <button className='btn btn-sm btn-dark'>Submit</button>
          </form>
          <br/><br/>
          {
            this.state.list.map((data) => {return(<List title={data} key={generateKey(data)}/>)})
          }

      </div>
    )
  }
}


export default ToDoLists

列表组件

import React, { Component } from 'react';
import '../App.css';

class List extends Component {
  constructor(props){
    super(props)
    this.state = {
      term: '',
      items: []
    };
    this.onChange = this.onChange.bind(this);
  }

  onChange = (event) => {
    this.setState({term: event.target.value});
  }
  onSubmit = (event) => {
    event.preventDefault()
    this.setState({
      term: '',
      items: [...this.state.items, this.state.term]
    })
  }

  render() {
    const generateKey = (x) => {
      return `${x}_${new Date().getTime()}`
    }

    return(
      <div>
        <h3>{this.props.title}</h3>
        <form onSubmit={this.onSubmit}>
          <input placeholder='Add New Todo Item' value={this.state.term} onChange={this.onChange}/>
          <button className='btn btn-sm btn-dark'>Submit</button>
        </form>
        <ul>
          {
            this.state.items.map((item) => {return(<li key={generateKey(item)}>{item}</li>)})
          }
        </ul>
      </div>
    )
  }
}


export default List

1 个答案:

答案 0 :(得分:0)

重置是由以下部分引起的:

 key={generateKey(data)}

无论您何时重新提交父级,子级都会获得新密钥,因为generateKey将返回几乎是随机的密钥。在进行差异化时,React会尝试找出哪些组件已被删除以及哪些是addee,并且它使用key道具来简化此过程。如果某个键是先前子级和当前子级的一部分,则该元素将保留在原位置,如果该键消失,则该组件将被销毁;如果该键是新的,它将创建一个新组件。因此,在您的情况下,只要运行List,所有ToDoLists.render()都将被销毁并创建新的。要更改此设置,只需使key保持不变:

 const generateKey = (x) => {
  return "" + x;
}

(如果两个列表的名称相同,最好将Lists索引作为键。)


虽然有效,但实际上现在很难存储状态,因为状态被分为多个部分。因此,您可能需要“提升状态”,以便在父级中管理所有列表,并且所有更改都将传播到该父级:

  class ToDoLists extends React.Component {
    constructor(props) {
      super(props);
      this.state = { lists: [] };
   }

   updateList(old, updated) {
    this.setState(({ lists }) => ({ lists: lists.map(l => l === old ? updated : l) }));
   }

   render() { return this.state.lists.map(list => <List list={list} onChange={updated => this.updateList(list, updated)} />); }
}

class List extends React.Component {
  onSubmit() {
    const { onChange, list } = this.props;
    this.setState({ term: "" });
    onChange([...list, this.state.term]);
  }
  //...
}