Implement Theming in React
Tags: react, javascript, usecontext, theming
Published: 2019-08-19 07:59:56

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](https://create-react-app.dev/). First of all we have to define a context globally with 

```javascript
export const ThemeContext = React.createContext({
  theme: {
    type: 'light',
    primary: '#00bfa5',
    text: '#black'
  },
  setTheme: () => {}
})
```
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.

```javascript
  return (
    <ThemeContext.Provider value={state}>
      {props.children}
    </ThemeContext.Provider>
  )
```

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.

```javascript
  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>
  )
}
```
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.

```javascript
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
```

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

```javascript
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>
  )
}
```

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

```javascript
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
```
I have written a more in depth post on theming similar to this you can also check that out. [Here](https://milddev.com/react/set-up-light-and-dark-theme-in-react/) is the link for that. [This](https://github.com/mateenkiani/react-tutorials/tree/master/set-up-light-and-dark-theme-react) 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](https://milddev.com) for other tutorials. Happy Coding!