How to get the theme outside styled-components?

做~自己de王妃 提交于 2019-12-03 11:57:34

EDIT: As of v1.2, my pull request got merged and you can use the withTheme higher order component this way:

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 post below

Solution I came up by now:

Create a Higher Order Component that will be responsable to get the current theme and pass as a prop to a component:

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} />
  }
}

Then, call it on the component you need to access the theme:

import Themable from './Themable.js'

const Component = ({ theme }) => <Card color={theme.color} />

export default Themable(Component);

Creating a HOC is a good way to tackle theming. Let me share another idea using React's Context.

Context allows you to pass data from a parent node to all it’s children. Each child may choose to get access to context by defining contextTypes in the component definition.

Let's say App.js is your root.

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;

Now our `ChildComponent.js who wants some theme and i18n strings

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 who only wants theme but not i18n. He might be stateless as well:

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;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!