简体   繁体   中英

React component setState() and meanwhile the parent component rerender itself

I built a React page like this:页 .
The switcher is binded to a callback function from the parent componentA and componentA get this function from top-level page. The callback updates top-level page's state. So when the switcher clicked, then top-level page will rerender the componentA.

The switcher I'm using is a component from React-Switch library: https://www.npmjs.com/package/react-switch

Then sometimes, when I click the switcher, there will be a warning:

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ReactSwitch component.

Here is some code snippet.
In top-level page:

    // In the top-level page, there is a state to decide whether or not to apply some data filter
    onSwitcherClicked(event) {
        this.setState({
            applyFilter: event,
    });

    render() {
        const filter = this.state.applyFilter ? '{paths:["/some_filters"],}' : '{paths:["/none"],}';
        return (
            <div>
                <ComponentA
                    filter = {filter}
                    applyFilter = {this.applyFilter}
                    callBack = {this.onSwitcherClicked}
                    />
            </div>
        );

In Component A

    // Component A
    componentWillMount() {
        // Send some API request according to this.props.filter and load the data
        // So every time the switcher clicked, the page will update the filter and pass some new props to componentA,
        // then ComponentA will remount it self
    }

    render() {
        return (
            <div>
                <DataViewer>
                    {/*A component to display the data*/}
                </DataViewer>
                <Switch onChange={this.props.callBack}
                        checked={this.props.applyFilter}/>
            </div>
        )
    }

Here is the error message"

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ReactSwitch component. 

printWarning warning.js:33
    warning warning.js:57
    React 3
        getInternalInstanceReadyForUpdate
        enqueueSetState
        setState
    $onDragStop react-switch.dev.js:252
    $onMouseUp react-switch.dev.js:277

I also copied the code in react-switch.dev.js:252 and react-switch.dev.js:277:

// react-switch.dev.js:252
252 this.setState({
253       $isDragging: false,
254       $hasOutline: false
255     });
256     this.$lastDragAt = Date.now();
// switch.dev.js:277
276 ReactSwitch.prototype.$onMouseUp = function $onMouseUp(event) {
277     this.$onDragStop(event);
278     window.removeEventListener("mousemove", this.$onMouseMove);
279    window.removeEventListener("mouseup", this.$onMouseUp);
280  };

I guess it's because when I click the switcher, it will reset the its own status. Meanwhile, the parent component's state is changed too. So when the switcher calls setState(), itself has been unmounted. Am I correct? Is there some approach to fix it?

Thank you!

Too long for a comment, but your component structure should look very similar to this kind of thing, in which case you wouldn't be getting that warning. I have a feeling you might be trying to duplicate the source of truth for state instead of just letting it flow down.

const ParentComponent = () => {
    const [isClicked,setIsClicked] = useState(false);


    return (
        ...
        <Switcher selected={isClicked} onClick={() => setIsClicked(!isClicked)}/>
    )

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM