如何在带有情感主题的样式化组件和插值中实现?

How can I implement in styled components and interpolations with emotion theming?

我一直在使用情感主题库开发具有动态主题的 React Web 应用程序。因此用户可以在环境之间切换,每个环境都有自己的主题。 我创建了自己的 CustomThemeProvider,我用它来动态更改主题。下面是代码。

export interface CustomThemeContextValue {
    customTheme?: Theme;
    setCustomTheme: (theme: Theme) => void;
};

const CustomThemeContext = React.createContext<CustomThemeContextValue>({
    customTheme: undefined,
    setCustomTheme: (theme) => { }
});

interface CustomThemeProviderProps {

}

export const CustomThemeProvider: FC<CustomThemeProviderProps> = (props) => {
    const [customTheme, setCustomTheme] = useState<Theme>(theme);

    const context: CustomThemeContextValue = React.useMemo(() => ({
        customTheme,
        setCustomTheme
    }), [customTheme, setCustomTheme]);

    return (
        <CustomThemeContext.Provider value={context}>
            <ThemeProvider theme={customTheme} {...props} />
        </CustomThemeContext.Provider>
    );
};

export const useCustomTheme = () => {
    const context = React.useContext(CustomThemeContext);
    if (!context) {
        throw new Error('useCustomTheme must be used within a CustomThemeProvider');
    }

    return context;
};

provider 像这样在 root 中实现

const Root = () => {
    return (
        <StrictMode>
            <CustomThemeProvider>
                <Normalize />
                <Global styles={globalStyle} />
                <App />
            </CustomThemeProvider>
        </StrictMode>
    );
};

所以这段代码有效,我可以使用 emotion useTheme 挂钩在函数组件中获取主题,如下所示:

const theme: Theme = useTheme();

但问题是如何从emotionThemeProvider中取出主题并在特定情况下使用。是否可以在

这样的上下文中使用它
export const style: Interpolation = {
    cssProp: value
};

或者它是否可以在如下上下文中使用,其中 styled.button 来自 emotion/styled。

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps> = styled.button([]);

它是否可用于 emotion/core 方法 css() 如下所示

const style = css({
    cssProp: value
});

我发现使用 google 很难找到这些问题的答案,所以我希望这里有人能帮助我。

所以过了一段时间我终于找到了我自己问题的答案,我想与大家分享,因为它很难找到。所以就在这里。

您可以像下面这样使用 InterpolationWithTheme 而不是 Interpolation:

import { InterpolationWithTheme } from '@emotion/core';

export const style: InterpolationWithTheme<Theme> = (theme) => ({
    cssProp: theme.value
});

这样你就可以从 ThemeProvider 中获取主题。

使用样式化的组件,您可以像下面这样实现它:

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps>
    = styled.button(({ theme }: any) => ([
    {
        cssProp: theme.value
    }
]);

最后,当您想将 css() 与 themeProvider 一起使用时,您必须将其替换为 InterpolationWithTheme 以使其像本答案的第一个示例中一样工作。

这些答案是通过结合查看 emotionjs docs 和检查 emotionjs types/interfaces.

找到的