umijs / umi

A framework in react community ✨
https://umijs.org
MIT License
15.05k stars 2.64k forks source link

[Bug] model 插件和 antd 改变主题互相冲突 #12394

Closed fz6m closed 1 month ago

fz6m commented 1 month ago

说明

antd 的插件中提供了一个 useAntdConfigSetter 的功能,它把 antd Config Provider 的配置管理成 state ,从而可以便捷的改变 antd Config Provider ,比如切换主题。来源:https://github.com/umijs/umi/pull/11856

但这个功能和 model 插件一起使用时,会发生冲突,复现代码的大致例子:

const setAntdConfig = useAntdConfigSetter()

 const changeTheme = () => {
    const { themeMode, antdToken } = getThemeToken();
    const targetThemeMode = themeMode === 'dark' ? 'light' : 'dark';
    // 将变量写入localStorage
    setThemeMode(targetThemeMode);
    const algorithm = targetThemeMode === 'light' ? [defaultAlgorithm] : [darkAlgorithm];
    const antdTheme: ThemeConfig = { algorithm };
    if (antdToken) {
      antdTheme.token = antdToken;
    }
    setAntdConfig({ theme: antdTheme });

注:不必拘泥于这段代码的写法,只要在 model 插件开启的时候,使用 setAntdConfig 去改变 antd 的主题,即可复现。

image

反馈来源:https://github.com/umijs/umi/discussions/12287

原因

经过初次探索,冲突原因大致如下:

antd config provider 的更新导致整个组件树重新渲染了,走到 model 的那一层 context 的时候,组件重新挂载,导致在重渲染的过程中执行了 setState (因为 model 的 context 里在第一次挂载的时候,急切的需要执行一次获取初始值的操作,而这个操作在执行的时候,正好处于 antd 重渲染的流程中),react 不允许这种行为,所以报错了。

期望的解决方式

因为 antd 的 setAntdConfig 其实是一种正确的 react 使用方式,而 model 的源码比较古老且 hack ,所以让 setAntdConfig 妥协不如修正 model ,所以期望能修正 model 源码来兼容这种用法解决,若实在无法修复,则退而次之再看看如何调整 setAntdConfig 妥协。

目前没有想到较好的方式解决,欢迎任何人贡献 PR

已有解决方案。

cc @xiaohuoni

xiaohuoni commented 1 month ago

没复现出来,谁帮忙给一下重现一下。 https://github.com/xiaohuoni/max-model-antd image

fz6m commented 1 month ago

知道原因了,你的这个 demo 让我找到了真正原因👍。