setState () внутри componentDidUpdate()
Я пишу скрипт, который перемещает выпадающий список ниже или выше ввода в зависимости от высоты выпадающего списка и положения ввода на экране. Также я хочу установить модификатор в выпадающее меню в соответствии с его направлением.
Но с помощью setState
внутри componentDidUpdate
создает бесконечный цикл(что очевидно)
Я нашел решение в использовании getDOMNode
и установка classname в выпадающее меню напрямую, но я чувствую, что должно быть лучшее решение с использованием инструментов React. Кто-нибудь может помочь я?
вот часть рабочего кода с getDOMNode
(i
немного пренебрегли логикой позиционирования для упрощения кода)
let SearchDropdown = React.createClass({
componentDidUpdate(params) {
let el = this.getDOMNode();
el.classList.remove('dropDown-top');
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
el.classList.add('dropDown-top');
}
},
render() {
let dataFeed = this.props.dataFeed;
return (
<DropDown >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
а вот код с setstate (который создает бесконечный цикл)
let SearchDropdown = React.createClass({
getInitialState() {
return {
top: false
};
},
componentDidUpdate(params) {
let el = this.getDOMNode();
if (this.state.top) {
this.setState({top: false});
}
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
if (!this.state.top) {
this.setState({top: true});
}
}
},
render() {
let dataFeed = this.props.dataFeed;
let class = cx({'dropDown-top' : this.state.top});
return (
<DropDown className={class} >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
5 ответов:
можно использовать
setState
внутриcomponentDidUpdate
. Проблема в том, что каким-то образом вы создаете бесконечный цикл, потому что нет условия останова.основываясь на том, что вам нужны значения, которые предоставляются браузером после визуализации компонента, я думаю, что ваш подход к использованию
componentDidUpdate
правильно, он просто нуждается в лучшей обработке условия, которое запускаетsetState
.
если вы используете
setState
внутриcomponentDidUpdate
он обновляет компонент, что приводит к вызовуcomponentDidUpdate
, который впоследствии называетsetState
снова приводит к бесконечному циклу. Вы должны условно позвонитьsetState
и убедитесь, что условие, нарушающее вызов, происходит в конечном итоге, например:componentDidUpdate: function() { if (condition) { this.setState({..}) } else { //do something else } }
если вы только обновляете компонент, отправляя ему реквизиты (он не обновляется setState, за исключением случая внутри componentDidUpdate), вы можете вызвать
setState
внутриcomponentWillReceiveProps
вместоcomponentDidUpdate
.
The
componentDidUpdate
подписьvoid::componentDidUpdate(previousProps, previousState)
. С помощью этого вы сможете проверить, какие реквизиты / состояние грязные и позвонитьsetState
соответственно.пример:
componentDidUpdate(previousProps, previousState) { if (previousProps.data !== this.props.data) { this.setState({/*....*/}) } }
Я бы сказал, что вы должны проверить, если государство уже имеет то же значение, которое вы пытаетесь установить. Если это то же самое, нет смысла снова устанавливать состояние для того же значения.
убедитесь, что вы установили свое состояние следующим образом:
let top = newValue /*true or false*/ if(top !== this.state.top){ this.setState({top}); }
У меня была аналогичная проблема, когда я должен центрировать подсказку. React setState в componentDidUpdate поставил меня в бесконечный цикл, я попробовал условие он работал. Но я обнаружил, что использование в обратном вызове ref дало мне более простое и чистое решение, если вы используете встроенную функцию для обратного вызова ref, вы столкнетесь с нулевой проблемой для каждого обновления компонента. Поэтому используйте ссылку на функцию в обратном вызове ref и установите там состояние, которое инициирует повторную визуализацию