【问题标题】:React component setState() and meanwhile the parent component rerender itselfReact 组件 setState() 并同时父组件重新渲染自己
【发布时间】:2020-08-19 08:34:36
【问题描述】:

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

我使用的切换器是来自 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.

这是一些代码 sn-p。
在顶级页面中:

    // 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() 时,它本身已经被卸载了。我对么?有什么方法可以解决吗?

谢谢!

【问题讨论】:

  • 不要猜,显示代码(请最少)。切换器组件不应卸载,即使它在其父组件中设置状态。
  • 好的,谢谢!我添加了一些代码 sn-p 和细节。
  • 您是否打错了您的顶级页面是const filter = this.applyFilter ? ... 应该是this.state.applyFilter
  • 对不起!这是一个错字。我修好了

标签: javascript reactjs setstate


【解决方案1】:

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

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


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

}

【讨论】:

    猜你喜欢
    • 2021-04-28
    • 2019-08-10
    • 1970-01-01
    • 2018-08-12
    • 2019-06-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    相关资源
    最近更新 更多