gabriel_tiso
gabriel_tiso

Reputation: 1137

Using the context API in React

I'm starting to work with the context api in React, and I decided to make a simple theme context. For now, if I go to my React DevTools and change the boolean isLightTheme to false, it works, but when i try to attach this functionality to a button, i keep getting errors. Can saomeone help me with that?

theme context

import React, { useState, createContext } from 'react'

export const ThemeContext = createContext()

export const ThemeContextProvider = ({ children }) => {
     const [state, setState] = useState({
         isLightTheme: true,
         light: { syntax: '#555', ui: '#ddd', bg: '#eee' },
         dark: { syntax: '#ddd', ui: '#333', bg: '#555' }
     })

     const toggleTheme = () => {
         setState({ isLightTheme: !state.isLightTheme})
     }

    return (
        <ThemeContext.Provider value={{...state, toggleTheme}}>
            {children}
        </ThemeContext.Provider>
    )
}
import React, { useContext } from 'react'
import { ThemeContext } from '../context/ThemeContext'

export const ThemeToggler = () => {

    const themeContext = useContext(ThemeContext)
    const { toggleTheme } = themeContext

    return (
        <button onClick={toggleTheme}>Change Theme</button>
    )
}

Upvotes: 1

Views: 118

Answers (1)

Hemant Parashar
Hemant Parashar

Reputation: 3774

The useState hooks API doesn't update a selective piece of state like setState does. It'll override the entire state. Here when you toggle the theme, the new state is only { isLightTheme: !state.isLightTheme} with no light and dark keys. You just need to handle this by only updating that piece of state. This should work :

import React, { useState, createContext } from 'react'

export const ThemeContext = createContext()

export const ThemeContextProvider = ({ children }) => {
     const [state, setState] = useState({
         isLightTheme: true,
         light: { syntax: '#555', ui: '#ddd', bg: '#eee' },
         dark: { syntax: '#ddd', ui: '#333', bg: '#555' }
     })

     const toggleTheme = () => {
         //preserve the remaining state also
         setState({...state,isLightTheme: !state.isLightTheme})
     }

    return (
        <ThemeContext.Provider value={{...state, toggleTheme}}>
            {children}
        </ThemeContext.Provider>
    )
}

Hope this helps !

Upvotes: 1

Related Questions