0

I am trying not to use Redux. So I am stuck with useContext in combination with useReducer for globaal state management. My problem: I can not update the state from a child component using dispatch.

Let me explain in more detail. My context file is pretty straight forward:

import React, { createContext } from "react";

const ActivateContext = createContext();

export default ActivateContext;

I import it in App.js and wrap it around the root component within my navigation:

import React, { useState, useReducer } from "react";
import Navigation from "./Navigation";
import ActivateContext from "./store/activate-context";

const Reducer = (state, action) => {
  if (action.type === "ACTIVATE_IT") return true;
};

export default function App() {

let initialState = false;
  const [state, dispatch] = useReducer(Reducer, initialState);

  return (
    <Provider store={store}>
      <ActivateContext.Provider  value={{activeStatus: state, activeDispatch: dispatch}}>
        <Navigation />
      </ActivateContext.Provider>
    </Provider>
  );

I then import "ActivateContext" in my child component called "Child". I save everything in the constant "activated". I then use "activated" in the prop called "access":

import React, {useContext} from "react";
import ActivateContext from "../../../store/activate-context";

function Child (props) {
  
const activated = useContext(ActivateContext);

   <MightComponent title="So Amazing" access={activated} />

I tried to add a button to the component "Child" to change the state in App.js but nothing happens:

   <TouchableOpacity
            onClick={() => ActivateContext.activeDispatch("ACTIVATE_IT")}
          >
            <Text>Testit</Text>
          </TouchableOpacity>

I know useContext works. If I i set "intitialState" to true in App.js and give it as a value to my provider, the "access" prop in the Child component receives "true", which makes the component change its style:

      <ActivateContext.Provider value={initialState}>
        <Navigation />
      </ActivateContext.Provider>

However I do not manage to use useContext to also pass down the dispatch function down the component tree...

Any help is much appreciated.

Thanks!

Twos22
  • 57
  • 1
  • 11

1 Answers1

1

I think you're trying to access your context values incorrectly in your onClick function, here:

onClick={() => ActivateContext.activeDispatch("ACTIVATE_IT")}

You're passing an object with two fields to your value prop:

<ActivateContext.Provider  value={{activeStatus: state, activeDispatch: dispatch}}>
  <Navigation />
</ActivateContext.Provider>

So you should be able to access both of these values, in your pages, doing something like:

const {activeStatus, activeDispatch} = useContext(ActivateContext);

And, since your dispatch expects an object with a type field, your onClick function would be something like:

onClick={() => activeDispatch({type: "ACTIVATE_IT"})}
joaocout
  • 518
  • 1
  • 5
  • 1
    Thank you very much! In my child I added `const {activeStatus, activeDispatch} = useContext(ActivateContext);` and changed `` into `` but it still seems not to work. Somehow, adding objects as value to the provider in App.js seems to make useContext stop working :-( Any ideas? – Twos22 Apr 28 '22 at 09:30
  • I just noticed something, you used 'onClick', but in React Native, we're supposed to use 'onPress', and that is probably what's making your code not work rn. Also, remember that your dispatch function expects an object with a 'type' field. – joaocout Apr 28 '22 at 17:18
  • I hope it works! – joaocout Apr 28 '22 at 17:26
  • 1
    Damn! That was it! It works now haha. I could have tried for ever! Thanks! – Twos22 Apr 28 '22 at 18:42