简体   繁体   中英

React components not rendering from global state using context API

I am trying to get my child component to look for the global state. As of now, I can log out my global state, I can see that it has been updated, but my components are not updating with the new value. I am not getting any errors but also have had a hard time find a good solution. I have the full repo(very small with only 1 component) if it helps here: https://github.com/jaysnel/context-api-react

Is there any reason my ChangeColor.js file is not updating with the new state change?

UpdateColor.js

import React, { useReducer, useEffect } from 'react'
import { useAppContext } from '../public/context/context'

export default function UpdateColor() {
    let { myGlobaData } = useAppContext();
    const [state, dispatch] = useReducer(reducer, myGlobaData);


    function reducer(state, action) {
        let newState = state.slice();
        console.log(state);
        if(newState !== undefined) {
            switch(action.type) {
                case 'UPDATE_COLOR':
                    newState[0].color = 'green';
                    return newState;
                default:
                    throw new Error();
            }
        }
    }

    return (
        <div>
            <button onClick={() => dispatch({type: 'UPDATE_COLOR'})}>Update Color</button>
        </div>
    )
}

ChangeColor.js

import React from 'react'
import { useAppContext } from '../public/context/context'

export default function ChangeColor() {

    const { myGlobaData } = useAppContext();
    console.log("ChangeColor.js", myGlobaData)

    return (
        <div>
            <h2 style={{color: myGlobaData[0].color}}>I Change Colors Based On Global State.</h2>
        </div>
    )
}

context.js

import { createContext, useContext } from 'react';


const AppContext = createContext();

export function AppWrapper({ children }) {
    const state = {
      myGlobaData: [
            {
                color: 'red',
                text: 'new text new me'
            }
      ],
    }


    return (
      <AppContext.Provider value={state}>
        {children}
      </AppContext.Provider>
    );
  }
  
  export function useAppContext() {
    return useContext(AppContext);
  }
  

I guess, your issue where did you used the reducer. Component ChangeColor.js don't know what are you doing inside UpdateColor.js . The solution is if put the reducer into global context context.js and then you have to acsess your reducer globally. I did created and pushed to github working example with two different approaches to using an actions reducer. working example

UpdateColor.js

import { useAppContext  } from '../public/context/context'

export default function UpdateColor() {
  const { dispatch } = useAppContext();

  const withPayload = () => {
     dispatch({
       type: 'UPDATE_COLOR_WITH_PAYLOAD',
       payload: {color: 'blue', text: 'new text from updateColor.js'}})
  }
  const intoReducer = () => {
     dispatch({type: 'UPDATE_COLOR_INTO_REDUCER'})
  }

  return (
    <div>
      <button onClick={withPayload}>Update Color with payload</button>
      <button onClick={intoReducer}>Update Color into reducer</button>
    </div>
  )
}

ChangeColor.js

import { useAppContext } from '../public/context/context'

export default function ChangeColor() {
  const { state } = useAppContext();

  return (
    <div>
      <h2 style={{color: state.color}}>I Change Colors Based On Global State.</h2>
      <p style={{textAlign: 'center'}}>{state.text}</p>
    </div>
  )   
}

context.js

import { createContext, useContext, useReducer } from 'react';

const AppContext = createContext();

export function useAppContext() {
  return useContext(AppContext);
}

function reducer(state, action) {
  switch (action.type) {
    case 'UPDATE_COLOR_WITH_PAYLOAD':
      return action.payload;
    case 'UPDATE_COLOR_INTO_REDUCER':
      action.color = 'green';
      action.text = 'new text from reducer';
      return action;
   default:
     return state;
  }
}

export function AppWrapper({ children }) {
   const initialState = { color: 'red', text: 'new text new me' };
   const [state, dispatch] = useReducer(reducer, initialState);
   return (
     <AppContext.Provider value={{ state, dispatch }}>
      {children}
     </AppContext.Provider>
   );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM