Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the theme outside styled-components?

I know how to get the theme from components that are created using the styled way:

const StyledView = styled.View`
    color: ${({ theme }) => theme.color};
`;

But how to get from normal components or apply it for different properties? Example:

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

like image 851
Bruno Lemos Avatar asked Nov 25 '16 02:11

Bruno Lemos


People also ask

Can you export styled-components?

styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API.

Where do I put theme providers?

1, <ThemeProvider/> should be used 'Just Once' in top-root component like index. js or App. js file created by 'create-react-app' tool. 2, <ThemeProvicer/> should be placed in 'Each root of React-component' literally.


2 Answers

You can use the useTheme hook since v5.0:

import React, { useTheme } from 'styled-components';

export function MyComponent() {
  const theme = useTheme();

  return <p style={{ color: theme.color }}>Text</p>;
}

You can also use the withTheme higher order component that I contributed a long time ago since v1.2:

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

While there is no official 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);
like image 142
Bruno Lemos Avatar answered Sep 17 '22 18:09

Bruno Lemos


You can use useTheme hook

import { useTheme } from 'styled-components';

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

  return (
    <View>
       <Card aCustomColorProperty={theme.color.sampleColor} />
    </View>
  );
};
like image 29
Yurii Brusentsov Avatar answered Sep 18 '22 18:09

Yurii Brusentsov