问题描述
在我们的项目中,我们以 AngularJS 为核心,我们正在过渡到 React。在 React 方面,我们使用带有自定义主题的 Chakra UI。
当加载 React 组件时,我们使用自定义主题的 ChakraProvider 包装组件,它看起来像这样:
<DesignProvider>
<FolderPermissionsIndicator {...props} />
</DesignProvider>
DesignProvider
在哪里:
import { ChakraProvider,ChakraProviderProps } from '@chakra-ui/react';
import * as React from 'react';
import { theme } from './theme';
import { useMemo } from 'react';
export const DesignProvider: React.FC<ChakraProviderProps> = props => {
const themeInstance = useMemo(() => theme,[]);
return (
<div data-ds-next={true}>
<ChakraProvider resetCSS={false} {...props} theme={themeInstance} />
</div>
);
};
主题是:
const theme: ChakraTheme = extendTheme({
styles: {
global: {
...gigantic object...
}
}
});
现在,这很好用,但是如果我们将很多组件嵌入到 AngularJS 中,并且每个组件都分别用 DesignProvider
包裹,事情就会变得很慢。
特别是,合并全球主题定制化需要一些时间。例如,如果我们从主题中删除 global
对象,则页面加载一次可能会从大约 20 秒到大约 500 毫秒。
其中一种解决方法当然是将该 global
部分拉入一个 css 文件并全局加载它。不过,这个解决方案有其自身的复杂性。
解决方法
Context API 是您问题的解决方案,创建上下文主题,您可以在其中存储主题对象。
来自 React 文档:
上下文旨在共享可被视为“全局”的数据 一棵 React 组件树,例如当前经过身份验证的用户, 主题或首选语言。
主题上下文.js:
import React,{ useState } from 'react';
export const ThemeContext = React.createContext({
theme :null
});
const ThemeContextProvider = props => {
const theme: ChakraTheme = extendTheme({
styles: {
global: {
...gigantic object...
}
}
});
const [themeState] = useState(theme);
return (
<ThemeContext.Provider
value={{ theme: themeState}}
>
{props.children}
</ThemeContext.Provider>
);
};
export default ThemeContextProvider;
组件设计提供者:
import { ChakraProvider,ChakraProviderProps } from '@chakra-ui/react';
import * as React from 'react';
import { ThemeContext } from './theme-context';
import { useMemo,useContext } from 'react';
export const DesignProvider: React.FC<ChakraProviderProps> = props => {
const themeInstance = useMemo(() => theme,[]);
const them = useContext(ThemeContext).theme;
return (
<div data-ds-next={true}>
<ChakraProvider resetCSS={false} {...props} theme={theme} />
</div>
);
};
最后一步:使用 ThemeContextProvider 包装您的应用:
<ThemeContextProvider>
<App/>
</ThemeContextProvider>
因此,每次使用组件 DesignProvider 时,您都不会重用巨型对象,而是会在运行时从 ThemeContext 中获取它们。