'Can I use the React Context API inside a Context API or do I have to merge them?

I am just curios about if it would be possible to use the Context API inside a Context API. Like for example I would have a Context API for an AppState and want to use that in another Context API which handles a WebSocket connection?



Solution 1:[1]

Inspired by Joseph's answer I am thinking about just using those both context api's in a custom hook together.

useMultipleContexts(){
  const contextOne = useContext(ContextOne);
  const contextTwo = useContext(ContextTwo);

  /**
   * Do something with both contexts
   * in a custom hook that can be used
   * multiple times with the same state
   */


}

Solution 2:[2]

This is a good scenario to use hooks instead of context.

// custom hook
function useAppState() {
  //add handlers here

  return appState;
}

function WebSocket() {
  const appState = useAppState();

  // do something (i.e reconnect) every time appState changes
  useEffect(() => { /* do something */, [appState])
}

function App() {
  return <WebSocket />
}

Solution 3:[3]

Let me explain how to use two different Contexts at the same time.

First step: You need to create two different context

const AppContext = React.createContext(null);
const SocketContext = React.createContext(null);

Second step: You need to implement your custom hook.

const UseSharedLogic = () => {
   // your common logic
}

Then share it using the context API.

 <AppContext.Provider value={state}>
        <SocketContext.Provider value={UseSharedLogic}>
          <App />
        </DispatchContext.Provider>
      </StateContext.Provider>

Third step: You need to consume these contexts at the component that you need to use them inside it.

const state = React.useContext(AppContext);
const socket = React.useContext(SocketContext);

Here you can use both contexts together and you use one value from one context in another one.

Let's assume that socket context has a function called connect and it depends on value from the app context, you can do something like this.

socket.connect(state.anyValue);

Solution 4:[4]

I would create a new functional component that would wrap the components

Say you had two components written as follows.

import React from 'react';
const ContextA = React.createContext({});
export default ContextA;
import React from 'react';
const ContextB = React.createContext({});
export default ContextB;

I generally avoid the above pattern because people have to guess what you're trying to put in the context. Instead I write a functional component that provides the context as follows

import { createContext, useContext } from 'react'
import ContextA from './contexta'
import ContextB from './contextb'

// The ! is needed in order to allow undefined to be set as the initial value.
const MyContext = createContext<IMyContextInfo>(undefined!);
export default ({children}) => {
  const { somethingFromA } = useContext(ContextA);
  const { somethingFromB }= useContext(ContextB);
  return (
    <MyContext.Provider value={{ a: somethingFromA, b: somethingFromB }}>
      {children}
    </MyContext.Provider>
  );
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bigTimer314
Solution 2 Joseph D.
Solution 3
Solution 4 Archimedes Trajano