🧐[问题] createInstance 的隔离性存在问题?
tommytroylin opened this issue · comments
🧐 问题描述
最近在使用 antd-style
结合 antd v5
进行组件二次开发定制
发现 createInstance
的行为与我的理解不一致,故留下此问题
按照我的理解。createInstance
会创建一套完全独立的样式 token 作用域(只依赖 antd Token)。来保证组件库混用时不会被污染。
但是实测行为不一致
💻 示例代码
import { ConfigProvider, Space, theme } from 'antd';
import { ThemeProvider, createInstance } from 'antd-style';
const instanceA = createInstance({ prefixCls: 'a', key: 'antd-a' });
const instanceB = createInstance({ prefixCls: 'b', key: 'antd-b' });
const useInstanceAStyles = instanceA.createStyles(() => {
return {};
});
const useInstanceBStyles = instanceB.createStyles(() => {
return {};
});
function AntdStyledComponent() {
const { token: antdRawToken } = theme.useToken();
const { theme: antdStyleThemeA } = useInstanceAStyles();
const { theme: antdStyleThemeB } = useInstanceBStyles();
return (
<Space direction="vertical">
<Space>
<div>antdRaw FontSize:</div>
<div>{antdRawToken.fontSize}</div>
</Space>
<Space>
<div>instanceA FontSize:</div>
<div>{antdStyleThemeA.fontSize}</div>
</Space>
<Space>
<div>instanceB FontSize:</div>
<div>{antdStyleThemeB.fontSize}</div>
</Space>
</Space>
);
}
function App() {
return (
<ConfigProvider theme={{ token: { fontSize: 12 } }}>
<AntdStyledComponent />
</ConfigProvider>
);
}
function App2() {
// 使用默认导出的 ThemeProvider
return (
<ThemeProvider>
<ConfigProvider theme={{ token: { fontSize: 12 } }}>
<AntdStyledComponent />
</ConfigProvider>
</ThemeProvider>
);
}
function App3() {
// 使用 instanceA 导出的 ThemeProvider
return (
<instanceA.ThemeProvider>
<ConfigProvider theme={{ token: { fontSize: 12 } }}>
<AntdStyledComponent />
</ConfigProvider>
</instanceA.ThemeProvider>
);
}
export default App3;
🚑 其他信息
App1 结果 符合预期
antdRaw FontSize:
12
instanceA FontSize:
12
instanceB FontSize:
12
App2 结果 instanceB 收到影响。不符预期?
antdRaw FontSize:
12
instanceA FontSize:
14
instanceB FontSize:
14
App3 即使使用不同的 instance 的 ThemeProvider ,结果 instanceB 依然收到影响。不符预期?
antdRaw FontSize:
12
instanceA FontSize:
14
instanceB FontSize:
14
Ok 我研究确认下
@arvinxx
简单排查了下
问题在 https://github.com/ant-design/antd-style/blob/master/src/functions/createInstance.ts#L84
这里若 createInstance 的时候不传递 styled.ThemeContext
到 https://github.com/ant-design/antd-style/blob/master/src/factories/createUseTheme.ts#L20
默认使用了 @emotion/react
的同一个 ThemeContext,最终导致没有隔离
有两种改法,具体看 api 的设计。
-
若 createInstance 不默认依赖 emotion 的 ThemeContext。则用户不传递时改成创建一个新的。内部创建自己默认实例时主动去传递 emotion ThemeContext。改造会符合个人理解的 api 语义。但是对当前所有配合 emotion 使用的用户来说是个潜在的 break change
-
若 createInstance 需要依赖 emotion 的 默认ThemeContext。那需要文档更新,在编写组件库要隔离的时候
必须传入类似{ styled: { ThemeContext: createContext({}) }}
配置
个人倾向是第一种。看看怎么改比较合适。我现在先在项目中绕过了
后续应该会选择第一种,有计划可能会在下个大版本中移除 @emotion/react
的依赖。