javascript - React 无法对未安装的组件执行状态更新
问题描述
我正在使用以下方法从其他组件控制我的标题。但是,我在更改页面时遇到了旧的“无法对未安装的组件执行反应状态更新”错误
export const store = {
state: {},
setState(value) {
this.state = value;
this.setters.forEach(setter => setter(this.state));
},
setters: []
};
store.setState = store.setState.bind(store);
export function useStore() {
const [ state, set ] = useState(store.state);
if (!store.setters.includes(set)) {
store.setters.push(set);
}
return [ state, store.setState ];
}
然后我的标题使用它来设置一个类并控制它是需要在白色上显示黑色还是在黑色上显示白色
const Header = () => {
const [type] = useStore();
render( ... do stuff )
};
我在页面上的组件导入 useStore 然后根据多种因素调用 setType,某些布局是一种类型,有些是其他类型,有些因 API 调用而异,因此有很多不同的组件需要调用该函数来设置标题状态。
const Flexible = (props) => {
const [type, setType] = useStore();
if( type !== 'dark ){ setType('dark') }
... do stuff
};
其自身的标头始终在页面上,位于路由器之前和外部,并且永远不会卸载。
这一切都很好,并设置了标题。但是,当我使用 React Router 更改页面时,出现无法设置状态错误。我不明白为什么会收到此错误。我首先认为组件可能会尝试使用 react 路由器再次运行,因此我将代码移动以将标头状态设置为仅在初始化时运行但没有帮助的 useEffect。
解决方案
您只会添加到设置器中,永远不会删除。因此,当组件卸载时,它将保留在设置器中,并且下次应用程序的其他部分尝试设置状态时,所有设置器都会被调用,包括卸载组件的设置器。这会导致您看到的错误。
您需要修改自定义挂钩以使用 useEffect,以便在卸载时可以使用拆卸逻辑。像这样的东西:
export function useStore() {
const [ state, set ] = useState(store.state);
useEffect(() => {
store.setters.push(set);
return () => {
const i = store.setters.indexOf(set);
if (i > -1) {
store.setters.splice(i, 1);
}
}
}, []);
return [ state, store.setState ];
}
推荐阅读
- python-3.x - 我正在运行一个 python azure devops 应用程序,它显示错误 /home/vsts/work/1/s\\Conf_Path.json
- mysql - 编译/重新编译mysql存储过程
- xamarin - OnAppearing 中的 await 是否意味着我正在导航的屏幕会立即显示?
- java - Java回文项目:If/else
- reactjs - 如何检查反应测试中的状态是否改变?
- sqlite - 如何分配排序数据集并分配顺序值?
- sql-server - T-SQL VARCHAR(MAX) 被截断 - 不显示问题
- jdbc - Simba JDBC 4.1 驱动程序的默认获取大小
- javascript - 如何根据函数参数推断 Promise 的返回类型?
- c# - 在 C# 中创建 Code128 条形码