vanyahuk
@vanyahuk

Почему неправильно работает shouldComponentUpdate после использования setState в функции?

есть коппонента
import React, {Component} from 'react';

import RaisedButton from 'material-ui/RaisedButton';

class BrandModels extends Component {

	constructor(props) {

		super(props);

		this.state = { items : [ undefined ] }


	}


	shouldComponentUpdate( nextProps, nextState ) {

		console.log( nextState.items, this.state.items )

		if ( nextState.items != this.state.items)
			return true;

		return false;

	}

	addGroup(){

		let items = this.state.items;

		items.push( undefined );

		this.setState({ items : items })

	}
	render() {
		return (
			<div
				className={country_brand_mod_list">
				
				<div className="row">
					<div className="col-12">
						<RaisedButton
							label={window._sharedData.loc.app.add}
							primary={true}
							onClick={this.addGroup.bind(this)}
						/>
					</div>
				</div>
			</div>
		)
	}

}

export default BrandModels;


после нажатия на кнопку добавляеться 1 елемент в массив стейта items

но, в shouldComponentUpdate nextState.items почему-то равно всегда this.state.items
5b0f1efbd1753295757972.png
  • Вопрос задан
  • 651 просмотр
Решения вопроса 2
0xD34F
@0xD34F Куратор тега React
в shouldComponentUpdate nextState.items почему-то равно всегда this.state.items

Разумеется - вы же не создаёте новый массив.

Замените

let items = this.state.items;
items.push( undefined );

на

let items = [ ...this.state.items, undefined ]
Ответ написан
rockon404
@rockon404 Куратор тега React
Frontend Developer
Потому что вы передаете в this.setState тот же массив.
Обновляйте так:

addGroup = () => {
  this.setState(prevState => ({ items : [ ...prevState.items, undefined ] }));
};

И уберите bind из render. В моем примере class field arrow function, ее биндить не надо.

Метод shouldComponentUpdate можно изменить так:
shouldComponentUpdate( nextProps, nextState ) {
   return nextState.items !== this.state.Items;
}

Если такой проверки мало, можно изменить так:
shouldComponentUpdate( nextProps, nextState ) {
   return nextState.items !== this.state.Items &&
     JSON.stringify(nextState.items.sort()) !== JSON.stringify(this.state.items.sort());
}

Если массив заменен, то пройдет приведение к строке и сравнение строк и если массивы разные вернется true и компонент обновится. Можно для сравнения использовать _.isEqual().
Но в большинстве случаев достаточно первого варианта с неглубоким сравнением.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы