如何获得样式组件外的主题?

时间:2016-11-25 02:46:15

标签: reactjs react-native styled-components

我知道如何从使用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 个答案:

答案 0 :(得分:10)

您可以使用 useTheme 钩子

import { useTheme } from 'styled-components';

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

  return (
    <View>
       <Card aCustomColorProperty={theme.color.sampleColor} />
    </View>
  );
};

答案 1 :(得分:8)

  

编辑:从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);

答案 2 :(得分:0)

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

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;

现在我们的` 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 谁只想要主题而不是i18n。他也可能是无国籍的:

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;

答案 3 :(得分:0)

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

高阶组件: 高阶组件或 HOC 是获取组件并在以某种方式对其进行增强后输出新组件的函数:
const EnhancedHOCComponent = hoc(OriginalReactComponent)

功能组件中带有主题的示例


const MyButton = ({theme}) => {
const red = theme.colors.red;

return (<div  style={{ color: red}} >how are you</div>)
}`

const Button =  withTheme(MyButton);
export default Button;