启用带有情感的全局主题?
Enable Global Theming with Emotion?
我关注了https://github.com/emotion-js/emotion/issues/546,Emotion的作者Kye提到了一个解决方法,虽然我不是很懂。
所以我做了一个小的 CodeSandBox 来实现问题中提供的细节。如何让 background-color
主题在 injectGlobal
中工作?
我找到了解决办法。完整的解决方案可以在 https://codesandbox.io/s/r76p996zym or https://github.com/deadcoder0904/emotion-global-theming
找到
制作一个 theme.js
包含您的应用程序主题的文件
theme.js
export const theme = {
LIGHT: {
textColor: "black",
bgColor: "white"
},
DARK: {
textColor: "white",
bgColor: "black"
}
};
将 Global
组件包装在 withTheme
中,它应该采用 theme
prop
Global.js
import React from "react";
import { injectGlobal } from "react-emotion";
import { withTheme } from "emotion-theming";
class Global extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.theme.bgColor !== prevProps.theme.bgColor) {
window.document.body.style.backgroundColor = this.props.theme.bgColor;
}
if (this.props.theme.textColor !== prevProps.theme.textColor) {
window.document.body.style.color = this.props.theme.textColor;
}
}
render() {
injectGlobal`
color: ${this.props.theme.textColor};
background-color: ${this.props.theme.bgColor};
`;
return React.Children.only(this.props.children);
}
}
export default withTheme(Global);
然后用 Global
组件包装您的 App
组件。由于 Global
组件需要 theme
它应该被包裹在 ThemeProvider
index.js
import React from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "emotion-theming";
import Global from "./injectGlobal";
import { theme } from "./theme";
class App extends React.Component {
state = {
isLight: true,
title: "Light Theme",
theme: theme.LIGHT
};
_toggleTheme = () => {
const { isLight } = this.state;
const title = isLight ? "Dark Theme" : "Light Theme";
const newTheme = isLight ? theme.DARK : theme.LIGHT;
this.setState({
isLight: !isLight,
title,
theme: newTheme
});
};
render() {
const { title, theme } = this.state;
return (
<ThemeProvider theme={theme}>
<Global>
<React.Fragment>
<h1>{title}</h1>
<button onClick={this._toggleTheme}>Toggle Theme</button>
</React.Fragment>
</Global>
</ThemeProvider>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
注意 - 此答案仅在 Emotion 10 发布和 API 更改之前有效。如果Emotion版本小于10,就用这个方案。
为使用情绪 10 的人们更新:
import React from 'react'
import { useTheme, ThemeProvider } from 'emotion-theming'
import { css, Global } from '@emotion/core'
const GlobalStyles = () => {
const theme = useTheme()
return (
<Global styles={css`
body {
background: ${theme.bg};
}
`} />
)
}
const App = () => (
<ThemeProvider theme={{ bg: 'tomato' }}>
<main>
<h1>Hi</h1>
<GlobalStyles />
</main>
</ThemeProvider>
)
我关注了https://github.com/emotion-js/emotion/issues/546,Emotion的作者Kye提到了一个解决方法,虽然我不是很懂。
所以我做了一个小的 CodeSandBox 来实现问题中提供的细节。如何让 background-color
主题在 injectGlobal
中工作?
我找到了解决办法。完整的解决方案可以在 https://codesandbox.io/s/r76p996zym or https://github.com/deadcoder0904/emotion-global-theming
找到制作一个 theme.js
包含您的应用程序主题的文件
theme.js
export const theme = {
LIGHT: {
textColor: "black",
bgColor: "white"
},
DARK: {
textColor: "white",
bgColor: "black"
}
};
将 Global
组件包装在 withTheme
中,它应该采用 theme
prop
Global.js
import React from "react";
import { injectGlobal } from "react-emotion";
import { withTheme } from "emotion-theming";
class Global extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.theme.bgColor !== prevProps.theme.bgColor) {
window.document.body.style.backgroundColor = this.props.theme.bgColor;
}
if (this.props.theme.textColor !== prevProps.theme.textColor) {
window.document.body.style.color = this.props.theme.textColor;
}
}
render() {
injectGlobal`
color: ${this.props.theme.textColor};
background-color: ${this.props.theme.bgColor};
`;
return React.Children.only(this.props.children);
}
}
export default withTheme(Global);
然后用 Global
组件包装您的 App
组件。由于 Global
组件需要 theme
它应该被包裹在 ThemeProvider
index.js
import React from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "emotion-theming";
import Global from "./injectGlobal";
import { theme } from "./theme";
class App extends React.Component {
state = {
isLight: true,
title: "Light Theme",
theme: theme.LIGHT
};
_toggleTheme = () => {
const { isLight } = this.state;
const title = isLight ? "Dark Theme" : "Light Theme";
const newTheme = isLight ? theme.DARK : theme.LIGHT;
this.setState({
isLight: !isLight,
title,
theme: newTheme
});
};
render() {
const { title, theme } = this.state;
return (
<ThemeProvider theme={theme}>
<Global>
<React.Fragment>
<h1>{title}</h1>
<button onClick={this._toggleTheme}>Toggle Theme</button>
</React.Fragment>
</Global>
</ThemeProvider>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
注意 - 此答案仅在 Emotion 10 发布和 API 更改之前有效。如果Emotion版本小于10,就用这个方案。
为使用情绪 10 的人们更新:
import React from 'react'
import { useTheme, ThemeProvider } from 'emotion-theming'
import { css, Global } from '@emotion/core'
const GlobalStyles = () => {
const theme = useTheme()
return (
<Global styles={css`
body {
background: ${theme.bg};
}
`} />
)
}
const App = () => (
<ThemeProvider theme={{ bg: 'tomato' }}>
<main>
<h1>Hi</h1>
<GlobalStyles />
</main>
</ThemeProvider>
)