componentDidUpdate()中的setState()

我正在编写一个脚本,根据下拉的高度和input在屏幕上的位置,在下方或上方移动下拉菜单。 另外我想根据其方向设置下拉菜单。 但是,使用componentDidUpdate内部的setState创build一个无限循环(这是显而易见的)

我已经find了一个解决scheme,使用getDOMNode和设置classname直接下拉,但我觉得应该有一个更好的解决scheme,使用React工具。 有谁能够帮助我?

这里是getDOMNode的工作代码的一部分(ia一点点被忽略的定位逻辑来简化代码)

 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的代码(创build一个无限循环)

 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> ); } }); 

您可以在componentDidUpdate使用setState 。 问题是,不知何故,你正在创造一个无限循环,因为没有rest条件。

基于事实,即一旦组件呈现,你需要浏览器提供的值,我认为你使用componentDidUpdate的方法是正确的,只需要更好地处理触发setState的条件。

如果在componentDidUpdate使用setState ,则会更新组件,导致对componentDidUpdate的调用,该componentDidUpdate随后会再次调用setState ,从而导致无限循环。 你应该有条件地调用setState并确保违反调用的条件最终发生,例如:

 componentDidUpdate: function() { if(condition) { this.setState({..}) } else { //do something else } } 

如果你只是通过发送道具来更新组件(它不会被setState更新,除了componentDidUpdate内的情况除外),你可以在componentWillReceiveProps而不是componentDidUpdate调用setState

componentDidUpdate签名是void::componentDidUpdate(previousProps, previousState) ,你可以testing哪些是props / state是脏的,所以你停止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}); } 

我有一个类似的问题,我必须居中工具提示。 在componentDidUpdate的React setState确实把我放在无限循环,我试图条件它的工作。 但我发现在refcallback中给了我更简单和干净的解决scheme,如果您使用内联函数进行refcallback,您将面对每个组件更新的空问题。 所以在refcallback中使用函数引用,并在那里设置状态,这将启动重新渲染