Javascript componentDidUpdate()的内部设置状态()

Javascript componentDidUpdate()的内部设置状态(),javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我正在写一个脚本,根据下拉列表的高度和输入在屏幕上的位置,将下拉列表移动到输入下方或上方。此外,我想设置修改器下拉根据其方向。 但是在componentDidUpdate内部使用setState会创建一个无限循环(这是显而易见的) 我在使用getDOMNode和直接将classname设置为下拉列表中找到了一个解决方案,但我觉得应该有一个更好的解决方案使用React工具。有人能帮我吗 下面是使用getDOMNode(i 一点被忽略的定位逻辑(简化代码) 让SearchDropdown=React

我正在写一个脚本,根据下拉列表的高度和输入在屏幕上的位置,将下拉列表移动到输入下方或上方。此外,我想设置修改器下拉根据其方向。 但是在
componentDidUpdate
内部使用
setState
会创建一个无限循环(这是显而易见的)

我在使用
getDOMNode
和直接将classname设置为下拉列表中找到了一个解决方案,但我觉得应该有一个更好的解决方案使用React工具。有人能帮我吗

下面是使用
getDOMNode
(i 一点被忽略的定位逻辑(简化代码)

让SearchDropdown=React.createClass({
componentDidUpdate(参数){
设el=this.getDOMNode();
el.classList.remove('dropDown-top');
如果(需要移动顶面(el)){
el.top=新值;
el.right=新的RightValue;
el.classList.add('dropDown-top');
}
},
render(){
让dataFeed=this.props.dataFeed;
返回(
{dataFeed.map((数据,i)=>{
返回();
})}
);
}
});
下面是setstate的代码(它创建了一个无限循环)

让SearchDropdown=React.createClass({
getInitialState(){
返回{
顶部:错误
};
},
componentDidUpdate(参数){
设el=this.getDOMNode();
if(this.state.top){
this.setState({top:false});
}
如果(需要移动顶面(el)){
el.top=新值;
el.right=新的RightValue;
如果(!this.state.top){
this.setState({top:true});
}
}
},
render(){
让dataFeed=this.props.dataFeed;
让class=cx({'dropDown-top':this.state.top});
返回(
{dataFeed.map((数据,i)=>{
返回();
})}
);
}
});

您可以在
componentdiddupdate
内部使用
setState
。问题是,不知何故,您正在创建一个无限循环,因为没有中断条件


基于组件渲染后需要浏览器提供的值这一事实,我认为您使用
componentdiddupdate
的方法是正确的,如果在
componentdiddupdate
中使用
setState
,它只需要更好地处理触发
setState

的条件,它更新组件,从而调用
componentdiddupdate
,随后再次调用
setState
,从而产生无限循环。您应该有条件地调用
setState
,并确保违反调用的条件最终发生,例如:

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

如果您仅通过向组件发送道具来更新组件(除componentDidUpdate内部的情况外,setState不会更新组件),则可以调用
setState
inside
componentWillReceiveProps
,而不是
componentDidUpdate

我遇到了一个类似的问题,我必须将工具提示居中。componentDidUpdate中的React-setState确实将我置于无限循环中,我尝试了它工作的条件。但我发现使用in-ref回调给了我更简单和干净的解决方案,如果您使用ref回调的内联函数,那么每次组件更新都会面临空值问题。因此,在ref callback中使用函数reference并在那里设置状态,这将启动重新渲染

我想说的是,您需要检查状态是否已经具有您试图设置的相同值。如果相同,则没有必要为相同的值再次设置状态

请确保将您的状态设置为:

let top = newValue /*true or false*/
if(top !== this.state.top){
    this.setState({top});
}

componentdiddupdate
签名是
void::componentdiddupdate(previousProps,previousState)
。这样,您就可以测试哪些道具/状态是脏的,并相应地调用
setState

例子:
此示例将帮助您了解反应生命周期挂钩

您可以在
getDerivedStateFromProps
方法中
setState
,即
static
并在
componentdiddupdate
中更改props后触发该方法

componentdiddupdate
中,您将获得3rd参数,该参数从
getSnapshotBeforeUpdate
返回

你可以查一下

//子组件
子类扩展了React.Component{
//加载组件时调用的第一件事
建造师(道具){
console.log(“构造函数”);
超级(道具);
此.state={
value:this.props.value,
颜色:“绿色”
};
}
//静态法
//无法访问“此”
//返回对象将更新状态
静态getDerivedStateFromProps(props,状态){
log(“getDerivedStateFromProps”);
返回{
价值:道具价值,
颜色:props.value%2==0?“绿色”:“红色”
};
}
//如果返回false,则跳过渲染
shouldComponentUpdate(下一步,下一步状态){
日志(“shouldComponentUpdate”);
//返回nextState.color!==this.state.color;
返回true;
}
//在真正的DOM更新之前(预提交)
//有权访问“this”
//返回对象将在componentDidUpdate中捕获
getSnapshotBeforeUpdate(prevProps,prevState){
log(“getSnapshotBeforeUpdate”);
返回{oldValue:prevState.value};
}
//组件更新后的调用
//使用快照访问以前的状态和道具
//可以在这里调用方法
//设置此内的状态将导致无限循环
componentDidUpdate(prevProps、prevState、快照){
log(“componentDidUpdate:”,prevProps,prevState,snapshot);
}
静态getDerivedStateFromError(错误){
log(“getDerivedStateFromError”);
返回{hasE
componentDidUpdate: function() {
    if (condition) {
        this.setState({..})
    } else {
        //do something else
    }
}
let top = newValue /*true or false*/
if(top !== this.state.top){
    this.setState({top});
}
componentDidUpdate(previousProps, previousState) {
    if (previousProps.data !== this.props.data) {
        this.setState({/*....*/})
    }
}
if(this.props.route.params.resetFields){

        this.props.route.params.resetFields = false;
        this.setState({broadcastMembersCount: 0,isLinkAttached: false,attachedAffiliatedLink:false,affilatedText: 'add your affiliate link'});
        this.resetSelectedContactAndGroups();
        this.hideNext = false;
        this.initialValue_1 = 140;
        this.initialValue_2 = 140;
        this.height = 20
    }