Не могу понять как работает метод componentWillUpdate

Я весь день смотрел в интернете и не нашел ничего полезного по этой теме. У меня есть вот такой код:

class User extends React.PureComponent {
    componentDidMount() {
        console.log("Did mount " + this.props.name);
    }

    componentDidUpdate(prevProps) {
        console.log("Did update " + prevProps.name + " -> " + this.props.name);
    }

    componentWillUnmount() {
        console.log("Will unmount " + this.props.name);
    }

    render() {
        return (
            <p>{this.props.name}</p>
        );
    }
}

class Users extends React.Component {
    constructor(props) {
        super(props);
        this.state = {usersList: props.usersList};
        this.removeUser = this.removeUser.bind(this);
    }

    removeUser(index) {
        let newUsers = this.state.usersList.filter((user, i) => i !== index);
        this.setState({
            usersList: newUsers
        });
    }

    render() {
        return (
            <div>
                {this.state.usersList.map((user, index) => {
                    return <User key={user.id} name={user.name} onClick={() => this.removeUser(index)}/>
                })}
                <button onClick={() => this.removeUser(1)}>Delete second</button>
            </div>
        );
    }
}

let users = [
    {
        id: 1,
        name: "Alexander"
    },
    {
        id: 2,
        name: "Anton"
    },
    {
        id: 3,
        name: "Dmitriy"
    },
    {
        id: 4,
        name: "Artem"
    },
    {
        id: 5,
        name: "Andrey"
    }
];

ReactDOM.render(
    <Users usersList={users}/>,
    document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Согласно тому, что я прочитал, PureComponent изменяется только при изменении state или props, но когда я нажимаю кнопку, я вижу сообщения от метода componentDidUpdate, даже если name не было изменено ни для одного User.


Ответы (1 шт):

Автор решения: Konstantin Modin

User получал функцию в пропс onClick которая пересоздавалась при каждом рендере, соответственно компонент обновлялся. Так же функция удаления-фильтрации пользователя была не правильно сделана. Нельзя использовать индекс массива. Нужно использовать индекс структуры данных. Получилось примерно так:

import React from "react";

class User extends React.PureComponent {
  componentDidMount() {
    console.log("Did mount " + this.props.name);
  }

  componentDidUpdate(prevProps) {
    console.log("Did update " + prevProps.name + " -> " + this.props.name);
  }

  componentWillUnmount() {
    console.log("Will unmount " + this.props.name);
  }

  render() {
    const { removeUser, id, name } = this.props;
    return <p onClick={() => removeUser(id)}>{name}</p>;
  }
}

const App = () => {
  return (
    <div>
      <Users usersList={users} />
    </div>
  );
};

export default App;

class Users extends React.Component {
  constructor(props) {
    super(props);
    this.state = { usersList: props.usersList };
    this.removeUser = this.removeUser.bind(this);
  }

  removeUser(id) {
    let newUsers = this.state.usersList.filter((user) => user.id !== id);
    this.setState({
      usersList: newUsers,
    });
  }

  render() {
    return (
      <div>
        {this.state.usersList.map((user) => {
          return (
            <User
              key={user.id}
              id={user.id}
              name={user.name}
              removeUser={this.removeUser}
            />
          );
        })}
        <button onClick={() => this.removeUser(2)}>Delete second</button>
      </div>
    );
  }
}

let users = [
  {
    id: 1,
    name: "Alexander",
  },
  {
    id: 2,
    name: "Anton",
  },
  {
    id: 3,
    name: "Dmitriy",
  },
  {
    id: 4,
    name: "Artem",
  },
  {
    id: 5,
    name: "Andrey",
  },
];

Если в Users написать вот так:

 <User
    key={user.id}
    id={user.id}
    name={user.name}
    removeUser={this.removeUser}
    onClick={() => {
       console.log("log");
    }}

то юзеры будут опять обновляться все. Можно добавить console.log в componentDidUpdate:

console.log(
      `prevProps.onClick === this.props.onClick`,
      prevProps.onClick === this.props.onClick
    );
→ Ссылка