Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle Nested Context Providers

I have a few nested Context Providers in my app that look like this

export const LangContext = React.createContext("javascript");
export const FontContext = React.createContext("mono-space");
export const FontSizeContext = React.createContext("16px");

const Store = ({ children }) => {
  const [lang, setLang] = useState("javascript");
  const [font, setFont] = useState("mono-space");
  const [fontSize, setFontSize] = useState("16px");
  return (
      <LangContext.Provider value={[lang, setLang]}>
        <FontContext.Provider value={[font, setFont]}>
          <FontSizeContext.Provider value={[fontSize, setFontSize]}>
              {children}
          </FontSizeContext.Provider>
        </FontContext.Provider>
      </LangContext.Provider>
  );
};

I'm sure this is a bad practice but I'm not sure how to handle this. I want to be able to create a single context provider for all the contexts.

like image 721
Alexandar Mahone Avatar asked Apr 19 '26 17:04

Alexandar Mahone


1 Answers

You can simply use a single provider and pass on the required values as an object:

export const StoreContext = React.createContext({});
const Store = ({ children }) => {
  const [lang, setLang] = useState("javascript");
  const [font, setFont] = useState("mono-space");
  const [fontSize, setFontSize] = useState("16px");
  return (
      <StoreContext.Provider value={{lang, setLang, font, setFont, fontSize, setFontSize}}>
              {children}
      </StoreContext.Provider>
  );
};

Also instead of using useState you could modify the above to use useReducer and make the API even simpler:

const initialState= {
   lang: 'javascript',
   font: 'mono-space',
   fontSize: '16px',
}

const reducer = (state, action) => {
    switch (action.type) {
        case 'SET_LANG': return {...state, lang: action.payload}
        case 'SET_FONT': return {...state, font: action.payload}
        case 'SET_FONTSIZE': return {...state, fontSize: action.payload}
        default: return state;
    }
}
export const StoreContext = React.createContext({});
const Store = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
      <StoreContext.Provider value={[state, dispatch]}>
              {children}
      </StoreContext.Provider>
  );
};

and in the child you can use it like:

const Child = () => {
    const [state, dispatch] = useContext(StoreContext);
    const handleChange = (size) => {
         dispatch({type: 'SET_FONTSIZE', payload: size})
    }
    ....
}
like image 160
Shubham Khatri Avatar answered Apr 21 '26 05:04

Shubham Khatri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!