Каким образом React размонтирует дочерние компоненты? - PullRequest
3 голосов
/ 14 апреля 2020

я вроде как новичок ie в React, но когда я узнал о методе componentWillUnmount (), я обнаружил поведение, которое не могу понять.

Рассмотрим этот скрипт (вот скрипка -> https://jsfiddle.net/ockhamsblade/4zf5tq2h/37/):

let myArray = [1,2,3,4,5,6];

class List extends React.Component {

  constructor() {
    super()
    this.state = {
      list: []
    };
  }

  componentDidMount() {
    this.setState({list:myArray});
  }
    render() {
    return (
    <div>
      <h1>My list</h1>
        <ul>
        {
            this.state.list.map((item, index) => (
            <Item key={index} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
          ))
            }
          </ul>
    </div>
    )
  }

  handleDelete = (value) => {
    console.log("Original list: ", this.state.list);
    console.log("Handling delete of item " + value);
    let newState = {...this.state};
    newState.list = newState.list.filter((v) => v !== value);
    console.log("New list: ", newState.list);
    this.setState(newState);
  }
}

class Item extends React.Component {
    render() {
  return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
  }

  delete = () => {
    console.log('Please remove item ' + this.props.value);
    this.props.onDeleteItem(this.props.value);
  }

  componentWillUnmount() {
    console.log("Unmounting item " + this.props.value);
  }
}

ReactDOM.render(<List />, document.querySelector("#app"))

Как вы могли проверить в скрипте JSFiddle. net (используя консоль разработчика), каждый раз, когда вы нажимаете на элемент, компонент List удаляет это значение из его состояние и повторно отображает остальные элементы. Все идет нормально. Дело в том, что перед размонтированием у компонентов Item всегда есть реквизиты последнего элемента, например, если они будут перезаписаны или что-то еще (вы можете проверить это в консоли разработчика). Таким образом, даже если я удаляю элемент № 3 (или любой другой), «this.props.value» для componentWillUnmount () всегда = 6, когда я ожидал бы = 3.

Я предполагаю, что по какой-либо причине производительности React удаляет последний элемент из DOM и повторно отображает остальные. Ожидается ли такое поведение? В таком случае, не могли бы вы сослаться на некоторые документы и / или сказать мне, как сохранить исходный экземпляр Предмета, удаляемый перед размонтированием? Я пытался сохранить значение props.value в состоянии элемента, но тоже не работает.

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 14 апреля 2020

Причина, по которой вы получаете это, заключается в том, что вы передаете индекс массива в качестве ключа. Вместо этого, если вы передадите действительный уникальный идентификатор, это не произойдет.

Пожалуйста, запустите этот код, который вы поймете.

let myArray = [1,2,3,4,5,6];

class List extends React.Component {

  constructor() {
    super()
    this.state = {
      list: []
    };
  }

  componentDidMount() {
    this.setState({list:myArray});
  }
    render() {
    return (
    <div>
      <h1>My list</h1>
        <ul>
        {
            this.state.list.map((item, index) => (
            <Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
          ))
            }
          </ul>
    </div>
    )
  }

  handleDelete = (value) => {
    console.log("Original list: ", this.state.list);
    console.log("Handling delete of item " + value);
    let newState = {...this.state};
    newState.list = newState.list.filter((v) => v !== value);
    console.log("New list: ", newState.list);
    this.setState(newState);
  }
}

class Item extends React.Component {
    render() {
  return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
  }

  delete = () => {
    console.log('Please remove item ' + this.props.value);
    this.props.onDeleteItem(this.props.value);
  }
  componentDidUpdate(){
    console.log("incdu",this.props.value);
  }

  componentWillUnmount() {
    console.log("Unmounting item " + this.props.value);
  }
}

ReactDOM.render(<List />, document.querySelector("#app"))

Единственное изменение, которое я сделал здесь, это передача правильного идентификатора (здесь сам элемент) как ключ.

<Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>

Вы можете обратиться Понимание уникальных ключей для дочерних элементов массива в React. js

1 голос
/ 14 апреля 2020

Это произошло из-за использования индекса в качестве ключа в вашем списке товаров. Это анти паттерн. для более подробной информации читайте здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...