ドロップダウンの高さと画面上の入力の位置に応じて、ドロップダウンを入力の下または上に移動するスクリプトを書いています。また、その方向に従って修飾子をドロップダウンに設定したいです。しかし、setState
内でcomponentDidUpdate
を使用すると、無限ループが作成されます(これは明らかです)
getDOMNode
を使用し、classnameを直接dropdownに設定することで解決策を見つけましたが、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>
);
}
});
setState
inside componentDidUpdate
を使用できます。問題は、ブレーク条件がないため、どういうわけか無限ループを作成していることです。
コンポーネントがレンダリングされた後、ブラウザによって提供される値が必要であるという事実に基づいて、componentDidUpdate
の使用に関するあなたのアプローチは正しいと思います。それは、setState
。
setState
内でcomponentDidUpdate
を使用すると、コンポーネントが更新され、その後componentDidUpdate
が呼び出され、その後setState
が再度呼び出され、無限ループが発生します。条件付きでsetState
を呼び出して、呼び出しに違反する条件が最終的に発生することを確認する必要があります。例:
componentDidUpdate: function() {
if (condition) {
this.setState({..})
} else {
//do something else
}
}
Propをコンポーネントに送信するだけでコンポーネントを更新する場合(componentDidUpdate内の場合を除き、setStateによって更新されません)、setState
の代わりにcomponentWillReceiveProps
内でcomponentDidUpdate
を呼び出すことができます。
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});
}
ToolTipを中央に配置する必要がある場合、同様の問題が発生しました。 componentDidUpdateのReact setStateによって無限ループに陥り、動作する状態を試しました。しかし、refコールバックで使用すると、よりシンプルでクリーンなソリューションが得られました.refコールバックにインライン関数を使用すると、コンポーネントの更新ごとにnullの問題に直面します。 refコールバックで関数参照を使用し、そこに状態を設定すると、再レンダリングが開始されます