Skip to main content

emotion-theme-provider-usetheme


position: 2

Emotion's ThemeProvider and useTheme

ThemeProvider and useTheme are utilities provided by Emotion that enable you to define and apply a consistent theme throughout your React application. This can include colors, fonts, spacing, and other design tokens.

ThemeProvider

ThemeProvider is a component that allows you to define a theme and make it available to all components within your application. It works similarly to React Context by providing the theme object to the component tree.

useTheme

useTheme is a hook that lets you access the theme object inside your functional components.

Example Usage

Step-by-Step Implementation

1. Install Emotion Packages

npm install @emotion/react @emotion/styled

2. Define a Theme Create a theme object with your design tokens.

// theme.js
export const theme = {
colors: {
primary: 'hotpink',
secondary: 'green',
},
spacing: {
small: '8px',
medium: '16px',
large: '32px',
},
};

3. Wrap Your Application with ThemeProvider Use ThemeProvider to make the theme available to your component tree.

// App.js
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { theme } from './theme';
import MyComponent from './MyComponent';

function App() {
return (
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
);
}

export default App;

4. Access the Theme with useTheme Use useTheme hook to access the theme inside your components.

// MyComponent.js
import React from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

const ThemedDiv = styled.div`
background-color: ${props => props.theme.colors.primary};
padding: ${props => props.theme.spacing.medium};
color: white;
`;

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

return (
<ThemedDiv>
This div is styled using the theme!
<p>The primary color is {theme.colors.primary}</p>
</ThemedDiv>
);
}

export default MyComponent;

Detailed Explanation

ThemeProvider

- Purpose: To provide a theme object to the component tree. - How it Works: It uses React Context internally to pass down the theme to all components within its subtree.

Example:

import React from 'react';
import { ThemeProvider } from '@emotion/react';

const theme = {
colors: {
primary: 'hotpink',
background: 'lightgray',
},
};

function App() {
return (
<ThemeProvider theme={theme}>
<div style={{ backgroundColor: theme.colors.background }}>
<h1 style={{ color: theme.colors.primary }}>Hello, Theme!</h1>
</div>
</ThemeProvider>
);
}

export default App;

useTheme

- Purpose: To access the theme object within functional components. - How it Works: It retrieves the theme from the nearest ThemeProvider using React's Context API.

Example:

import React from 'react';
import { useTheme } from '@emotion/react';

function ThemedComponent() {
const theme = useTheme();

return (
<div style={{ color: theme.colors.primary }}>
This text is using the primary color from the theme.
</div>
);
}

export default ThemedComponent;

Combining Both in a Real-World Scenario

You can use both ThemeProvider and useTheme to create a cohesive theming system for your application.

Example:

// theme.js
export const theme = {
colors: {
primary: 'hotpink',
secondary: 'green',
background: 'lightgray',
},
spacing: {
small: '8px',
medium: '16px',
large: '32px',
},
};

// App.js
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { theme } from './theme';
import ThemedComponent from './ThemedComponent';

function App() {
return (
<ThemeProvider theme={theme}>
<div style={{ backgroundColor: theme.colors.background }}>
<ThemedComponent />
</div>
</ThemeProvider>
);
}

export default App;

// ThemedComponent.js
import React from 'react';
import { useTheme } from '@emotion/react';

function ThemedComponent() {
const theme = useTheme();

return (
<div style={{ padding: theme.spacing.medium, color: theme.colors.primary }}>
This component is styled using the theme.
</div>
);
}

export default ThemedComponent;

Difference Between import { theme } from './theme'; and import { useTheme } from '@emotion/react';

Both import { theme } from './theme'; and import { useTheme } from '@emotion/react'; are used to work with themes in a React application, but they serve different purposes and come from different sources.

1. import { theme } from './theme';

- Source: This import statement typically comes from a custom file (e.g., theme.js) where the theme object is defined. - Purpose: The theme object contains design tokens such as colors, spacing, typography, etc., which you define and use throughout your application. - Usage: This is used to provide the theme object to the ThemeProvider so that it can be made available to the entire component tree.

Example of theme.js:

// theme.js
export const theme = {
colors: {
primary: 'hotpink',
secondary: 'green',
background: 'lightgray',
},
spacing: {
small: '8px',
medium: '16px',
large: '32px',
},
};

Example of using theme with ThemeProvider:

// App.js
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { theme } from './theme';
import ThemedComponent from './ThemedComponent';

function App() {
return (
<ThemeProvider theme={theme}>
<ThemedComponent />
</ThemeProvider>
);
}

export default App;

2. import { useTheme } from '@emotion/react';

- Source: This import statement comes from the @emotion/react library. - Purpose: useTheme is a hook that allows functional components to access the theme object provided by ThemeProvider. - Usage: This hook is used within a component to get the current theme object and apply its values directly in the component's styles or logic.

Example of using useTheme:

// ThemedComponent.js
import React from 'react';
import { useTheme } from '@emotion/react';

function ThemedComponent() {
const theme = useTheme();

return (
<div style={{ padding: theme.spacing.medium, color: theme.colors.primary }}>
This component is styled using the theme.
</div>
);
}

export default ThemedComponent;

Key Differences

1. Definition vs. Consumption: - theme is defined in your custom file (theme.js) and contains all the design tokens. - useTheme is used to consume the theme object within functional components.

2. Usage Context: - theme is passed to ThemeProvider to make the theme available throughout the app. - useTheme is used within components to access the theme object.

3. Source: - theme is imported from a custom file you create and define. - useTheme is imported from the @emotion/react library.

Practical Example Combining Both

// theme.js
export const theme = {
colors: {
primary: 'hotpink',
secondary: 'green',
background: 'lightgray',
},
spacing: {
small: '8px',
medium: '16px',
large: '32px',
},
};

// App.js
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { theme } from './theme';
import ThemedComponent from './ThemedComponent';

function App() {
return (
<ThemeProvider theme={theme}>
<div style={{ backgroundColor: theme.colors.background }}>
<ThemedComponent />
</div>
</ThemeProvider>
);
}

export default App;

// ThemedComponent.js
import React from 'react';
import { useTheme } from '@emotion/react';

function ThemedComponent() {
const theme = useTheme();

return (
<div style={{ padding: theme.spacing.medium, color: theme.colors.primary }}>
This component is styled using the theme.
</div>
);
}

export default ThemedComponent;

References

- Emotion Documentation - Styled Components in Emotion - MDN Web Docs: React Context API