Как обновить состояние (используя ReactJS), если я не позволю setState в componentWillUpdate?
Когда я setState
в componentWillUpdate
, componentWillUpdate
работает в бесконечном цикле, который не прекращает запускаться.
Это никогда не дает моему render
возможность отразить мои изменения. Как изменить состояние, если я не должен использовать componentWillUpdate
?
Изменить: у меня уже есть понимание, что setState
не следует вызывать в компоненте componentWillUpdate. Я просто смущен тем, что должен сделать в качестве альтернативы.
Изменить №2: я начал с componentWillReceiveProps
, но я не могу запустить эту функцию, когда меняет состояние родительского компонента. Я предоставляю это состояние от родителя в качестве реквизита для моего ребенка.
Ответы
Ответ 1
Первое, что нужно сделать, это проверить официальную документацию для этого метода (ссылка). Где вы можете прочитать, когда функция фактически вызывается.
Затем прочитайте общую ошибку (примечание):
Вы не можете использовать this.setState() в этом методе. Если вам нужно обновить состояние в ответ на изменение прокрутки, вместо этого используйте componentWillReceiveProps.
Вы меняете состояние, а React автоматически вызывает componentWillUpdate
.
Ответ 2
Я понимаю, что это предостережено в руководстве, но я не уверен, что вижу проблему с вызовом setState
из componentWillUpdate
. Правда, это может привести к бесконечной рекурсии , если, конечно, вы не предоставите дно этой рекурсии (способ вырваться из нее). Например. можно было бы проверить второй (nextState
) параметр в componentWillUpdate
и не вызывать setState
снова, если выполнено какое-либо условие (то есть, когда заканчивается рекурсия).
В качестве минимального примера представьте компонент, который не имеет свойств вообще, только два состояния. Далее представьте, что вторая часть состояния асинхронно получается из первой. Например. первая часть состояния может быть некоторым параметром для вызова Ajax, а вторая часть состояния является результатом этого вызова. Поэтому в основном вы вызываете this.setState
для настройки параметров, а затем внутри componentWillUpdate
вы можете сделать что-то вроде следующего (чтобы все было просто, я использую window.setTimeout
в качестве заполнителя для вызова Ajax):
const ComponentWithAsyncState = React.createClass({
getInitialState: function() {
return {
ajaxParams: '',
ajaxResult: ''
};
},
setAjaxParams: function(params) {
this.setState({ajaxParams: params});
},
componentWillUpdate: function(_, nextState) {
if (nextState.ajaxParams!=this.state.ajaxParams)
window.setTimeout(function imagineThisIsAjax() {
this.setState({ajaxResult: `result from ${nextState.ajaxParams}`});
}.bind(this), 2000);
},
Когда (например, через некоторые элементы управления, управляемые этим компонентом) изменение ajaxParams
, последовательность действий будет чем-то вроде (где ~~>
обозначает асинхронность):
setAjaxParams --> this.setState --> componentWillUpdate ~~> imagineThisIsAjax --> this.setState --> componentWillUpdate
т.е. второй вызов componentWillUpdate
не приведет к дальнейшему this.setState
, и, таким образом, рекурсия закончится там.