【问题标题】:React parent component reseting child components state when parent state updates父状态更新时反应父组件重置子组件状态
【发布时间】:2018-10-05 19:04:57
【问题描述】:

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

List 组件允许您添加待办事项。 例如:包含早餐、淋浴、剃须等待办事项的晨间日程清单。

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

我不确定这是否是尝试这样做的正确方法。这是因为我在添加新列表时需要传递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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    重置是由这个小部分引起的:

     key={generateKey(data)}
    

    每当您重新渲染父级时,子级都会获得新的密钥,因为generateKey 返回一个几乎随机的密钥。在进行差异化时,React 会尝试找出哪些组件被删除以及哪些组件被添加,它使用 key 属性来简化这一点。如果键是先前子元素和当前子元素的一部分,则元素将保持原样,如果键消失,则组件将被销毁,如果键是新的,它将创建一个新组件。因此,在您的情况下,所有Lists 都将被销毁,并且每当ToDoLists.render() 运行时都会创建新的。要改变这一点,只需让key 持久化:

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

    (如果两个列表可能具有相同的名称,那么将列表索引作为键可能是个好主意。)


    虽然这可行,但实际上现在很难存储状态,因为它被拆分为多个组件。因此,您可能希望“提升状态”,以便所有列表都在父级中进行管理,并且每个更改都会传播到该父级:

      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]);
      }
      //...
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-10
      • 1970-01-01
      • 1970-01-01
      • 2021-04-06
      • 2018-11-03
      • 2021-03-02
      • 2022-06-29
      • 2021-07-07
      • 2017-05-05
      相关资源
      最近更新 更多