poldeeek
poldeeek

Reputation: 333

How to get the React context from another context?

I have two contexts - gameContext, roundContext. I am using useReducer to manipulate the state. Can I dispatch action in gameContext from roundContext reducer (RoundReducer)?

The reducer function is defined outside RoundProvider component.

const RoundReducer = (state: RoundStateType, action: any) => {
   ///sth
}

const RoundProvider: React.FC<{}> = ({ children }) => {
  const [state, dispatch] = useReducer(RoundReducer, initState);

  return (
    <RoundContext.Provider
      value={{ roundState: state, roundDispatch: dispatch }}>
      {children}
    </RoundContext.Provider>
  );
};

The GameProvider component looks the same.

Upvotes: 1

Views: 2707

Answers (2)

Chris Farmer
Chris Farmer

Reputation: 25386

If you have nested contexts GameContext and RoundContext you can access the outer game context from the inner round, then call a setter/dispatch method to initiate a change in each. The inner RoundContext provider is inside the GameContext provider, so there (dispatch in this example) you have access to the methods exposed by the GameContext.

const GameContext = React.createContext(null);
const GameProvider = ({ children }) => {
  const [gameState, setGameState] = React.useState();
  return (
    <GameContext.Provider value={{ gameState, setGameState }}>
      {children}
    </GameContext.Provider>
  );
};
const useGame = () => React.useContext(GameContext)

const RoundContext = React.createContext(null);
const RoundProvider = () => {
  const { gameState, setGameState } = useGame();
  const [roundState, setRoundState] = React.useState();

  const dispatch = (value) => {
    // Do something to both the round and the game state
    setGameState(value.toUpperCase());
    setRoundState(value);
  };

  return (
    <RoundContext.Provider value={{ roundState, dispatch }}>
      {children}
    </RoundContext.Provider>
  );
}
const useRound = () => React.useContext(RoundContext)

const Main = () => {
  const game = useGame()
  const round = useRound()
  const handleAction = () => {
    round.dispatch('some value that also goes to the game')
  }
  return <>
    <input type='text' onChange={handleAction} />
    <div>{game.gameState}</div>
    <div>{round.roundState}</div> 
  </>
}

const App = () => (<GameProvider>
  <RoundProvider>
    <Main />
  </RoundProvider>
</GameProvider>)

Here's a codesandbox example: https://codesandbox.io/s/xenodochial-wind-gkhje

Upvotes: 2

Milan Patel
Milan Patel

Reputation: 144

pass the prop from the game context to roundContext or other way around, let say if you're using react hooks - useState,in props pass the setValue.

Please review the following code.

also, this is just for referance

export default function GameComponent(){
//suppose this is parent component and you want to change the value from child componenet
const [value, setValue] = useState("Patel");
return(
<div>
<h1>{value}</h1>
<RoundComponent setValue={setValue} value={value} />
//pass props like this
</div>
)
}

now coming back to round component

export default function RoundComponent(props){

return(
<div>
<input type="text" name="name" value={props.value} onChange={e=>props.setValue(e.target.value)}/>
</div>
)
} 

I hope this answers your question.

Upvotes: 0

Related Questions