0

在我们的项目中,我们以 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 文件并全局加载它。不过,这种解决方案也有其自身的复杂性。

是否有更简单的方法可以在所有组件之间共享自定义主题?

4

1 回答 1

0

Context API是您的问题的解决方案,创建可以存储主题对象的上下文主题。

从反应文档:

Context 旨在共享可被视为 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 获取它们。

于 2021-05-12T01:06:31.783 回答