Home > Blockchain >  Updating context data from a wrapper around a provider in React
Updating context data from a wrapper around a provider in React

Time:03-10

I have the following set up in my codebase (taken direct:

LanguageContextMangement.js

import React, { useState } from 'react'

export const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
})

export const LanguageContextProvider = (props) => {

  const setLanguage = (language) => {
    setState({...state, language: language})
  }

  const initState = {
    language: "en",
    setLanguage: setLanguage
  } 

  const [state, setState] = useState(initState)

  return (
    <LanguageContext.Provider value={state}>
      {props.children}
    </LanguageContext.Provider>
  )
}

App.js

import React, { useContext } from 'react'
import { LanguageContextProvider, LanguageContext } from './LanguageContextManagement'

function App() {

  const state = useContext(LanguageContext)

  return (
    <LanguageContextProvider>
      <button onClick={() => state.setLanguage('pk')}>
        Current Language is: {state.language}
      </button>
    </LanguageContextProvider>
  )
}

export default App

I would expect the language to update to "pk" when clicking on the button, but it seems to not work. An explanation about what is going wrong here would be very much appreciated (and how to fix it). Trying to understand React context and hooks.

CodePudding user response:

The useContext function should be called from a component that is inside the Provider. You are currently calling the function from within, but it's still being initialised outside the provider. So currently the useContext tries to use a context that isn't created yet. A solution would be to create a new component that calls useContext and renders your button; this way the sequence of creating the context and then using the context is correct.

Example:

import React, { useState, useContext } from "react";

const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

const LanguageContextProvider = (props) => {
  const setLanguage = (language) => {
    setState({ ...state, language: language });
  };

  const initState = {
    language: "en",
    setLanguage: setLanguage
  };

  const [state, setState] = useState(initState);

  return (
    <LanguageContext.Provider value={state}>
      {props.children}
    </LanguageContext.Provider>
  );
};

const Button = () => {
  const state = useContext(LanguageContext);
  return (
    <button onClick={() => state.setLanguage("pk")}>
      Current Language is: {state.language}
    </button>
  );
};

function App() {
  return (
    <LanguageContextProvider>
      <Button />
    </LanguageContextProvider>
  );
}

export default App;
  • Related