Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧐[问题] createInstance 的隔离性存在问题? #114

Open
tommytroylin opened this issue Sep 27, 2023 · 3 comments
Open

🧐[问题] createInstance 的隔离性存在问题? #114

tommytroylin opened this issue Sep 27, 2023 · 3 comments

Comments

@tommytroylin
Copy link

🧐 问题描述

最近在使用 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
@arvinxx
Copy link
Collaborator

arvinxx commented Sep 27, 2023

Ok 我研究确认下

@tommytroylin
Copy link
Author

@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 的设计。

  1. 若 createInstance 不默认依赖 emotion 的 ThemeContext。则用户不传递时改成创建一个新的。内部创建自己默认实例时主动去传递 emotion ThemeContext。改造会符合个人理解的 api 语义。但是对当前所有配合 emotion 使用的用户来说是个潜在的 break change

  2. 若 createInstance 需要依赖 emotion 的 默认ThemeContext。那需要文档更新,在编写组件库要隔离的时候
    必须传入类似 { styled: { ThemeContext: createContext({}) }} 配置

个人倾向是第一种。看看怎么改比较合适。我现在先在项目中绕过了

@arvinxx
Copy link
Collaborator

arvinxx commented Dec 8, 2023

后续应该会选择第一种,有计划可能会在下个大版本中移除 @emotion/react 的依赖。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants