首页 > 解决方案 > React 组件 setState() 并同时父组件重新渲染自己

问题描述

我构建了一个这样的 React 页面: 页.
切换器绑定到父组件A的回调函数,组件A从顶级页面获取此函数。回调更新顶级页面的状态。所以当切换器点击时,顶层页面将重新渲染组件A。

我使用的切换器是 React-Switch 库中的一个组件:https ://www.npmjs.com/package/react-switch

然后有时,当我单击切换器时,会出现警告:

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.

这是一些代码片段。
在顶级页面中:

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

在组件 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>
        )
    }

这是错误消息”

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

我还复制了 react-switch.dev.js:252 和 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  };

我猜是因为当我点击切换器时,它会重置自己的状态。同时,父组件的状态也发生了变化。所以当切换器调用 setState() 时,它本身已经被卸载了。我对么?有什么方法可以解决吗?

谢谢!

标签: javascriptreactjssetstate

解决方案


评论太长了,但是您的组件结构应该看起来与这种东西非常相似,在这种情况下您不会收到该警告。我有一种感觉,你可能试图复制状态的真相来源,而不是让它流下来。

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


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

}

推荐阅读