DEV Community

Mateen Kiani
Mateen Kiani

Posted on • Originally published at milddev.com

Implement Theming in React

When I started web development in react I decided to add theming functionality in my webapp that is to switch the theme of every single component inside my website by a single click. There are many guides available on the internet but I think they are quite difficult for beginners so here is a simple approach to add theming in your webapp.

What do you need to know?

Well there are a few concepts that you will learn through the way. To understand things quickly have a look at these concepts (i.e useContext and UseState hooks in React - React Context API ). If you already know these concepts then you are good to go, also you will find this post pretty straight forward.

Now Moving on to the Coding part

I have created my project with create-react-app. First of all we have to define a context globally with

export const ThemeContext = React.createContext({
  theme: {
    type: 'light',
    primary: '#00bfa5',
    text: '#black'
  },
  setTheme: () => {}
})
Enter fullscreen mode Exit fullscreen mode

Ofcourse whenever you need to use the value of context you have to import it first otherwise you will get an undefined error. Now our context named ThemeContext is defined globally but to be able to consume its value we must wrap the components with ThemeContext.provider with some initial value. After this we can use the value of context inside child components.

  return (
    <ThemeContext.Provider value={state}>
      {props.children}
    </ThemeContext.Provider>
  )
Enter fullscreen mode Exit fullscreen mode

Now you should be thinking where the hell did I define this {state} variable. Well be patient this is a bit tricky, I have made this state an object that can store multiple values as well as methods as const. I did this because I will be updating the value of context by accessing this state object. If this sounds confusing to you see the code below hopefully you will understand it.

  export const ThemeContextProvider = props => {
  const theme = {
    light: {
      type: 'light',
      primary: '#0277bd',
      text: 'black'
    },
    dark:{
      type: 'dark',
      primary: '#212121',
      text: 'white'
    },
  }

  const setTheme = type => {
    setState({ ...state, theme: type === 'dark' ? theme.light : theme.dark })
  }

  const initState = {
    theme: theme.light,
    setTheme: setTheme
  }

  const [state, setState] = useState(initState)

  return (
    <ThemeContext.Provider value={state}>
      {props.children}
    </ThemeContext.Provider>
  )
}
Enter fullscreen mode Exit fullscreen mode

As I have to update the value of state object I have used a useState hook for that. For those who don't know about this hook I would say whenever we need to update the state of our component in functional components we must use this hook. Though there is also a useReducer hook for that but I will cover that in another post. For now you should think of it as the only way to update the state of a component.

Toggle Theme Component

I have created this component to switch theme of my website from anywhere inside our app, but one thing that you need to keep in mind is that you should wrap all of your components with ThemeProvider component because when we are switching theme we call a setState method that updates the value of Context.

import React, { useContext } from 'react'
import { ThemeContext } from './ThemeProvider'

function ToggleTheme() {
  const state = useContext(ThemeContext)

  const btn = {
    color: state.theme.textOnSecondary,
    marginTop: '20px',
    marginBottom: '20px',
    background: state.theme.secondary
  }

  return (
    <button
      variant='contained'
      onClick={() => {
        state.setTheme(state.theme.type)
      }}
      style={btn}
    >
      Toggle Theme
    </button>
  )
}

export default ToggleTheme
Enter fullscreen mode Exit fullscreen mode

You should have noticed that I haven't set the colour of any component yet. Now to change the colour of your component with the change in value of context we have to set the value of colour from our context value like this

import React, { useContext } from 'react'
import { ThemeContext } from './ThemeProvider'

export default function Footer() {
  const state = useContext(ThemeContext)

  const footer = {
    backgroundColor: state.theme.primary,
    color: state.theme.text,
    width: '100%',
    height: '50px',
  }

  return (
   <div style={footer}>
     This is a Footer
   </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Finally this is how my App.js File looks like:

import React from 'react'
import { ThemeContextProvider } from './components/ThemeProvider'
import AppBar from './components/AppBar'
import Footer from './components/Footer'
import ToggleTheme from './components/ToggleTheme'

function App() {

 return (
    <ThemeContextProvider>
      <AppBar />
      <ToggleTheme />
      <Footer />
    </ThemeContextProvider>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

I have written a more in depth post on theming similar to this you can also check that out. Here is the link for that. This is the link to my github repository for this post. If you have any question let me know in the comments section.

Also don't forget to checkout my website for other tutorials. Happy Coding!

Top comments (0)