setState() inside of componentDidUpdate()

I'm writing a script which moves dropdown below or above input depending on height of dropdown and position of the input on the screen. Also I want to set modifier to dropdown according to its direction. But using setState inside of the componentDidUpdate creates an infinite loop(which is obvious)

I've found a solution in using getDOMNode and setting classname to dropdown directly, but i feel that there should be a better solution using React tools. Can anybody help me?

Here is a part of working code with getDOMNode (i a little bit neglected positioning logic to simplify code)

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

and here is code with setstate (which creates an infinite loop)

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

Solution 1:

You can use setStateinside componentDidUpdate. The problem is that somehow you are creating an infinite loop because there's no break condition.

Based on the fact that you need values that are provided by the browser once the component is rendered, I think your approach about using componentDidUpdate is correct, it just needs better handling of the condition that triggers the setState.

Solution 2:

The componentDidUpdate signature is void::componentDidUpdate(previousProps, previousState). With this you will be able to test which props/state are dirty and call setState accordingly.

Example:

componentDidUpdate(previousProps, previousState) {
    if (previousProps.data !== this.props.data) {
        this.setState({/*....*/})
    }
}