0

In a sample mini app I have index.js which renders <App /> (with ReactDOM.render method). And <App /> is:

import { useReducer } from 'react';

import AppContext, { defaultAppState } from './store/AppContext';
import AppReducer from './store/AppReducer';

import CitiesList from './components/CitiesList';
import AddCity from './components/AddCity';

export default function App() {
  const [appState, dispatch] = useReducer(AppReducer, defaultAppState);
  return (
    <AppContext.Provider value={[ appState, dispatch ]}> 
      <CitiesList />
      <AddCity />
    </AppContext.Provider>
  );  
}

The context is defined in a file like this (AppContext.js):

import React from 'react';

export const defaultAppState = { 
  cities: [
    {name: 'CityA', temperature: 20},
    {name: 'CityB', temperature: 12},
  ],
};

export default React.createContext(
  defaultAppState
);

And the reducer is this one (AppReducer.js):

import { defaultAppState } from './AppContext';
import * as ACTIONS from './Actions';

const AppReducer = (state = defaultAppState, action) => {
  switch(action.type) {
    case ACTIONS.ADD_CITY:
      const newCities = state.cities.concat([action.payload]);
      return { ...state, cities: newCities };
    default:
      return state;
  }
}

export default AppReducer;

In <AddCity /> component I'm successfully triggering dispatch and update the state in the reducer. (Placed console.log just before the return and saw that it's what the new state is supposed to be.) However, this does not trigger re-rendering and <CitiesList /> doesn't reflect any change - it always shows the default state.

Any idea what I'm doing wrong?

=====

EDIT: Adding the code of <CitiesList />:

import React, { useContext } from 'react';
import AppContext from '../store/AppContext';

export default function CitiesList() {

  const [appState, dispatch] = useContext(AppContext);

  const { cities } = appState;

  return (
    <>  
      <h1>Cities ({cities.length})</h1>
      {cities.length > 0 &&
        // Looping the cities array and showing the actual cities ..
      }   
    </> 
  );  
}

Adding the code of <AddCity /> as well:

import { useState, useReducer } from 'react';

import AppReducer from '../store/AppReducer';
import { ADD_CITY } from '../store/Actions';

export default function AddCity() {

  const [appReducer, dispatch] = useReducer(AppReducer);
  const [name, setName] = useState('');

  const onButtonClick = e => {
    const newCityData = { name: name, temperature: 18 };
    dispatch({type: ADD_CITY, payload: newCityData});
    setName('');
  };  

  return (
    <>  
      <input value={name} onChange={e => setName(e.target.value)} />
      <br/>
      <button onClick={onButtonClick}>Add city</button>
    </> 
  );  
}
pesho hristov
  • 1,946
  • 1
  • 25
  • 43
  • You forgot to share the code in CitiesList. I think you didn't consume context right-way in CitiesList. useContext(AppContext) – ndthanhdev Oct 27 '21 at 17:05
  • @ndthanhdev, I just did. Initially I didn't add it because I didn't want the initial post to be too long. – pesho hristov Oct 27 '21 at 17:11
  • try to log `appState` under ` const [appState, dispatch] = ...` – ndthanhdev Oct 27 '21 at 17:46
  • @ndthanhdev - it always shows the default one. ... In the reducer, when I dispatch the event, I see the list changes, but in the views I always get the default ones. – pesho hristov Oct 27 '21 at 18:01
  • I think you should share the code in AddCity too. – ndthanhdev Oct 27 '21 at 18:08
  • I think you are using useReducer instead of useContext in AddCity – ndthanhdev Oct 27 '21 at 18:09
  • @ndthanhdev - I just added the code for ``. Also - yes, I'm using the `useReducer` there cause I want to update the cities list. Is that a problem? – pesho hristov Oct 27 '21 at 18:26
  • you want to update the state in the global context so you have to use dispatch from useContext. – ndthanhdev Oct 27 '21 at 18:38
  • in AddCity, try this `const [_unused, dispatch] = useConetxt(AppContext);` – ndthanhdev Oct 27 '21 at 18:43
  • @ndthanhdev - I get it now :) ... I had to use the dispatch from the context, and the Provider puts the dispatch there pulling it from the reducer ... right? ... I just tried it and it works :) ... so how about you answer and I'll accept your answer ... thus you'll make a bit more reputation ;) – pesho hristov Oct 28 '21 at 08:43

0 Answers0