Не могу понять как работает метод 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 шт):
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
);