首页 > 解决方案 > useContext + useReducer 不会导致重新渲染(始终提供默认状态)

问题描述

在一个示例迷你应用程序中,我有 index.js 呈现<App />(使用 ReactDOM.render 方法)。并且<App />是:

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>
  );  
}

上下文在这样的文件(AppContext.js)中定义:

import React from 'react';

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

export default React.createContext(
  defaultAppState
);

而reducer就是这个(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;

<AddCity />组件中,我成功触发dispatch并更新了减速器中的状态。(将 console.log 放在 之前return并看到它应该是新状态。)但是,这不会触发重新渲染并且<CitiesList />不会反映任何更改 - 它始终显示默认状态。

知道我做错了什么吗?

=====

编辑:添加代码<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 ..
      }   
    </> 
  );  
}

同时添加以下代码<AddCity />

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>
    </> 
  );  
}

标签: reactjsuse-contextuse-reducer

解决方案


推荐阅读