如何在 styled-components 之外获取主题?
How to get the theme outside styled-components?
我知道如何从使用 styled
方式创建的组件中获取 theme
:
const StyledView = styled.View`
color: ${({ theme }) => theme.color};
`;
但是如何从普通组件获取或将其应用于不同的属性?示例:
index.js
<ThemeProvider theme={{ color: 'red' }}>
<Main />
</ThemeProvider>
main.js
<View>
<Card aCustomColorProperty={GET COLOR FROM THEME HERE} />
</View>
Notice how the property that needs the theme is not called style
从 v5.0 开始,您可以使用 useTheme
挂钩:
import React, { useTheme } from 'styled-components';
export function MyComponent() {
const theme = useTheme();
return <p style={{ color: theme.color }}>Text</p>;
}
你也可以使用我很久以前从v1.2开始贡献的withTheme高阶组件:
import { withTheme } from 'styled-components'
class MyComponent extends React.Component {
render() {
const { theme } = this.props
console.log('Current theme: ', theme);
// ...
}
}
export default withTheme(MyComponent)
original response below (ignore this!)
虽然没有正式的解决方案,但我现在想出了:
创建一个高阶组件,负责获取当前主题并作为 prop 传递给组件:
import React from 'react';
import { CHANNEL } from 'styled-components/lib/models/ThemeProvider';
export default Component => class extends React.Component {
static contextTypes = {
[CHANNEL]: React.PropTypes.func,
};
state = {
theme: undefined,
};
componentWillMount() {
const subscribe = this.context[CHANNEL];
this.unsubscribe = subscribe(theme => {
this.setState({ theme })
});
}
componentWillUnmount() {
if (typeof this.unsubscribe === 'function') this.unsubscribe();
}
render() {
const { theme } = this.state;
return <Component theme={theme} {...this.props} />
}
}
然后,在你需要访问的组件上调用它 theme
:
import Themable from './Themable.js'
const Component = ({ theme }) => <Card color={theme.color} />
export default Themable(Component);
创建 HOC 是解决主题化的好方法。让我使用 React 的 Context.
分享另一个想法
Context 允许您将数据从 parent 节点传递给它的所有 children。
每个 child 可以选择通过在组件定义中定义 contextTypes
来访问 context
。
假设 App.js 是您的根。
import themingConfig from 'config/themes';
import i18nConfig from 'config/themes';
import ChildComponent from './ChildComponent';
import AnotherChild from './AnotherChild';
class App extends React.Component {
getChildContext() {
return {
theme: themingConfig,
i18n: i18nConfig, // I am just showing another common use case of context
}
}
render() {
return (
<View>
<ChildComponent />
<AnotherChild myText="hola world" />
</View>
);
}
}
App.childContextTypes = {
theme: React.PropTypes.object,
i18n: React.PropTypes.object
};
export default App;
现在我们的 `ChildComponent.js 谁想要一些主题和 i18n 字符串
class ChildComponent extends React.Component {
render() {
const { i18n, theme } = this.context;
return (
<View style={theme.textBox}>
<Text style={theme.baseText}>
{i18n.someText}
</Text>
</View>
);
}
}
ChildComponent.contextTypes = {
theme: React.PropTypes.object,
i18n: React.PropTypes.object
};
export default ChildComponent;
AnotherChild.js 只想要主题不想要国际化的人。他也可能是无国籍人:
const AnotherChild = (props, context) {
const { theme } = this.context;
return (<Text style={theme.baseText}>{props.myText}</Text>);
}
AnotherChild.propTypes = {
myText: React.PropTypes.string
};
AnotherChild.contextTypes = {
theme: React.PropTypes.object
};
export default AnotherChild;
要在功能组件中使用 withTheme
,请创建 Higher-order-component。
Higher-order-component:
higher-order components, or HOCs, are functions that take a component and output a new component after enhancing it in some manner:
const EnhancedHOCComponent = hoc(OriginalReactComponent)
功能组件中的 withTheme 示例
const MyButton = ({theme}) => {
const red = theme.colors.red;
return (<div style={{ color: red}} >how are you</div>)
}`
const Button = withTheme(MyButton);
export default Button;
你可以使用useTheme
挂钩
import { useTheme } from 'styled-components';
const ExampleComponent = () => {
const theme = useTheme();
return (
<View>
<Card aCustomColorProperty={theme.color.sampleColor} />
</View>
);
};
我知道如何从使用 styled
方式创建的组件中获取 theme
:
const StyledView = styled.View`
color: ${({ theme }) => theme.color};
`;
但是如何从普通组件获取或将其应用于不同的属性?示例:
index.js
<ThemeProvider theme={{ color: 'red' }}>
<Main />
</ThemeProvider>
main.js
<View>
<Card aCustomColorProperty={GET COLOR FROM THEME HERE} />
</View>
Notice how the property that needs the theme is not called
style
从 v5.0 开始,您可以使用 useTheme
挂钩:
import React, { useTheme } from 'styled-components';
export function MyComponent() {
const theme = useTheme();
return <p style={{ color: theme.color }}>Text</p>;
}
你也可以使用我很久以前从v1.2开始贡献的withTheme高阶组件:
import { withTheme } from 'styled-components'
class MyComponent extends React.Component {
render() {
const { theme } = this.props
console.log('Current theme: ', theme);
// ...
}
}
export default withTheme(MyComponent)
original response below (ignore this!)
虽然没有正式的解决方案,但我现在想出了:
创建一个高阶组件,负责获取当前主题并作为 prop 传递给组件:
import React from 'react';
import { CHANNEL } from 'styled-components/lib/models/ThemeProvider';
export default Component => class extends React.Component {
static contextTypes = {
[CHANNEL]: React.PropTypes.func,
};
state = {
theme: undefined,
};
componentWillMount() {
const subscribe = this.context[CHANNEL];
this.unsubscribe = subscribe(theme => {
this.setState({ theme })
});
}
componentWillUnmount() {
if (typeof this.unsubscribe === 'function') this.unsubscribe();
}
render() {
const { theme } = this.state;
return <Component theme={theme} {...this.props} />
}
}
然后,在你需要访问的组件上调用它 theme
:
import Themable from './Themable.js'
const Component = ({ theme }) => <Card color={theme.color} />
export default Themable(Component);
创建 HOC 是解决主题化的好方法。让我使用 React 的 Context.
分享另一个想法Context 允许您将数据从 parent 节点传递给它的所有 children。
每个 child 可以选择通过在组件定义中定义 contextTypes
来访问 context
。
假设 App.js 是您的根。
import themingConfig from 'config/themes';
import i18nConfig from 'config/themes';
import ChildComponent from './ChildComponent';
import AnotherChild from './AnotherChild';
class App extends React.Component {
getChildContext() {
return {
theme: themingConfig,
i18n: i18nConfig, // I am just showing another common use case of context
}
}
render() {
return (
<View>
<ChildComponent />
<AnotherChild myText="hola world" />
</View>
);
}
}
App.childContextTypes = {
theme: React.PropTypes.object,
i18n: React.PropTypes.object
};
export default App;
现在我们的 `ChildComponent.js 谁想要一些主题和 i18n 字符串
class ChildComponent extends React.Component {
render() {
const { i18n, theme } = this.context;
return (
<View style={theme.textBox}>
<Text style={theme.baseText}>
{i18n.someText}
</Text>
</View>
);
}
}
ChildComponent.contextTypes = {
theme: React.PropTypes.object,
i18n: React.PropTypes.object
};
export default ChildComponent;
AnotherChild.js 只想要主题不想要国际化的人。他也可能是无国籍人:
const AnotherChild = (props, context) {
const { theme } = this.context;
return (<Text style={theme.baseText}>{props.myText}</Text>);
}
AnotherChild.propTypes = {
myText: React.PropTypes.string
};
AnotherChild.contextTypes = {
theme: React.PropTypes.object
};
export default AnotherChild;
要在功能组件中使用 withTheme
,请创建 Higher-order-component。
Higher-order-component: higher-order components, or HOCs, are functions that take a component and output a new component after enhancing it in some manner:
const EnhancedHOCComponent = hoc(OriginalReactComponent)
功能组件中的 withTheme 示例
const MyButton = ({theme}) => {
const red = theme.colors.red;
return (<div style={{ color: red}} >how are you</div>)
}`
const Button = withTheme(MyButton);
export default Button;
你可以使用useTheme
挂钩
import { useTheme } from 'styled-components';
const ExampleComponent = () => {
const theme = useTheme();
return (
<View>
<Card aCustomColorProperty={theme.color.sampleColor} />
</View>
);
};