Подтвердить что ты не робот

Как обновить состояние (используя ReactJS), если я не позволю setState в componentWillUpdate?

Когда я setState в componentWillUpdate, componentWillUpdate работает в бесконечном цикле, который не прекращает запускаться.

Это никогда не дает моему render возможность отразить мои изменения. Как изменить состояние, если я не должен использовать componentWillUpdate?

Изменить: у меня уже есть понимание, что setState не следует вызывать в компоненте componentWillUpdate. Я просто смущен тем, что должен сделать в качестве альтернативы.

Изменить №2: я начал с componentWillReceiveProps, но я не могу запустить эту функцию, когда меняет состояние родительского компонента. Я предоставляю это состояние от родителя в качестве реквизита для моего ребенка.

4b9b3361

Ответ 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, и, таким образом, рекурсия закончится там.