20

我知道如何theme从使用以下方式创建的组件中获取styled

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>

注意没有调用需要主题的属性style

4

4 回答 4

25

从 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)



下面的原始回复(忽略这个!)

虽然没有官方解决方案,但我现在想出了:

创建一个高阶组件,它将负责获取当前主题并作为道具传递给组件:

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);
于 2016-11-25T06:34:05.530 回答
15

你可以使用useTheme钩子

import { useTheme } from 'styled-components';

const ExampleComponent = () => {
  const theme = useTheme();

  return (
    <View>
       <Card aCustomColorProperty={theme.color.sampleColor} />
    </View>
  );
};
于 2021-01-05T15:38:52.653 回答
0

创建 HOC 是解决主题的好方法。让我分享另一个使用React 的 Context的想法。

上下文允许您将数据从父节点传递给它的所有子节点。每个孩子都可以选择context通过contextTypes在组件定义中定义来访问。

假设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;

现在我们想要一些主题和 i18n 字符串的ChildComponent.js

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;

只想要主题而不想要 i18n 的另一个Child.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;
于 2016-11-28T15:43:17.523 回答
0

withTheme在功能组件中使用,请创建一个高阶组件。

高阶组件:高阶组件或HOC是采用组件并在以某种方式增强后输出新组件的功能:
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;
于 2020-09-10T19:43:39.570 回答