Redux 在 componentWillUnmount 中取消订阅仍然调用订阅回调

Redux unsubscribe within componentWillUnmount still calls subscribe callback

我正在手动将 React 组件连接到 Redux 存储。是的,我认识 Redux 的 Dan Abramov。我最终会着手研究 react-redux,但现在我想了解发生了什么。

componentDidMount() {
    this.unsubscribe = store.subscribe(() => {
        const storeState = store.getState();
        this.setState({
            someData: storeState.someData
        });
    }.bind(this));
}
componentWillUnmount () {
    this.unsubscribe();
}

这是我在标签页组件中的一些代码。当用户更改选项卡以显示不同的数据时,这些选项卡页会在父组件中换入和换出。我已经通过调试器并确认当用户更改选项卡时,将按顺序发生以下情况:

  1. 前一个选项卡已卸载(componentWillUnmount 触发并调用 this.unsubscribe()this 是前一个选项卡组件,正如预期的那样)
  2. 新选项卡已安装。 (componentDidMount 触发并且 this 是新的选项卡组件,正如预期的那样)
  3. setState 在订阅回调中被调用,this 是 PREVIOUS TAB,并且反应报错:

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 Tab component.

这对我来说似乎很奇怪。不应该调用 unsubscribe 因为我已经阻止在未安装的组件上调用此回调? 似乎表明按照我所做的操作应该可以消除此警告,并且只是在质疑这是否是个好主意。但就我而言,它仍然存在。

我认为这不重要,但我使用的是 ES6 "class" 语法,而原来的语法似乎并不重要。

subscribe(listener: () => void): Unsubscribe;

让我们阅读订阅方法文档。

  1. The subscriptions are snapshotted just before every dispatch() call. If you subscribe or unsubscribe while the listeners are being invoked, this will not have any effect on the dispatch() that is currently in progress. However, the next dispatch() call, whether nested or not, will use a more recent snapshot of the subscription list.

由于您首先调用了 dispatch 方法,所有侦听器都会被调用,您的取消订阅调用只会在下一次调度调用时发生。