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中使用函数引用,并在那里设置状态,这将启动重新渲染