Я пишу сценарий, который перемещает раскрывающийся список ниже или выше ввода в зависимости от высоты раскрывающегося списка и положения ввода на экране. Также я хочу установить модификатор для раскрывающегося списка в соответствии с его направлением. Но использование setState
внутри componentDidUpdate
создает бесконечный цикл (что очевидно)
Я нашел решение в использовании getDOMNode
и настройке имени класса в раскрывающемся списке напрямую, но я считаю, что должно быть лучшее решение с использованием инструментов React. Кто-нибудь может мне помочь?
Вот часть рабочего кода с getDOMNode
(например, немного упущенной логикой позиционирования для упрощения кода)
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>
);
}
});
javascript
reactjs
ecmascript-6
Катерина Павленко
источник
источник
setState
будет выполняться повторный рендеринг. Вместо того, чтобы проверять и вызывать несколько раз, просто отслеживайте, что вы хотите видеть в локальной переменной, а затем один раз в конце вызова, только если ваша локальная переменная не совпадает . В его нынешнем виде вы сразу же перезагружаетесь после первого повторного рендеринга, что помещает вас в бесконечный цикл.state.top
setState
state.top
componentDidUpdate
setState
state.top
state.top
componentDidUpdate
в этой скрипке .componentShouldUpdate
?Ответы:
Можно использовать
setState
внутрьcomponentDidUpdate
. Проблема в том, что каким-то образом вы создаете бесконечный цикл, потому что нет условия разрыва.Основываясь на том факте, что вам нужны значения, которые предоставляются браузером после рендеринга компонента, я думаю, что ваш подход к использованию
componentDidUpdate
правильный, ему просто нужна лучшая обработка условия, которое запускаетsetState
.источник
componentDidUpdate
и может быть просто добавлено по мере необходимостиrender
вместо этого.componentDidUpdate
Подписьvoid::componentDidUpdate(previousProps, previousState)
. С его помощью вы сможете проверить, какие свойства / состояния загрязнены, иsetState
соответственно вызвать .Пример:
источник
componentDidMount
не имеет аргументов и вызывается только при создании компонента, поэтому не может использоваться для описанной цели.componentDidMount
, поэтому, когда я писал ответ, известное имя каскадировалось 😮 Еще раз спасибо и отличное наверстывание!componentDidUpdate(prevProps, prevState) { if ( prevState.x!== this.state.x) { //Do Something } }
Если вы используете
setState
внутри,componentDidUpdate
он обновляет компонент, что приводит к вызову,componentDidUpdate
который впоследствии вызываетsetState
снова, что приводит к бесконечному циклу. Вы должны условно позвонитьsetState
и убедиться, что в конечном итоге возникает условие, нарушающее вызов, например:Если вы обновляете только компонент, отправляя ему реквизиты (он не обновляется с помощью setState, за исключением случая внутри componentDidUpdate), вы можете вызвать
setState
внутриcomponentWillReceiveProps
вместоcomponentDidUpdate
.источник
getDerivedStateFromProps
.Этот пример поможет вам разобраться в хуках жизненного цикла React .
Вы можете
setState
вgetDerivedStateFromProps
методе iestatic
и запускать метод после изменения реквизитаcomponentDidUpdate
.В
componentDidUpdate
вы получите 3 - ю из параметров , который возвращает изgetSnapshotBeforeUpdate
.Вы можете проверить эту ссылку codeandbox
источник
Я бы сказал, что вам нужно проверить, имеет ли состояние уже то же значение, которое вы пытаетесь установить. Если это то же самое, нет смысла снова устанавливать состояние для того же значения.
Обязательно установите свое состояние следующим образом:
источник
У меня была аналогичная проблема, когда мне приходилось центрировать подсказку. React setState в componentDidUpdate поставил меня в бесконечный цикл, я попробовал условие, которое сработало. Но я обнаружил, что использование в обратном вызове ref дало мне более простое и чистое решение, если вы используете встроенную функцию для обратного вызова ref, вы столкнетесь с нулевой проблемой при каждом обновлении компонента. Поэтому используйте ссылку на функцию в обратном вызове ref и установите там состояние, которое инициирует повторную визуализацию
источник