为啥 React 的 useReducer 在第一次在 useEffect 上获取数据时返回空状态?

Posted

技术标签:

【中文标题】为啥 React 的 useReducer 在第一次在 useEffect 上获取数据时返回空状态?【英文标题】:Why does React's useReducer returns an empty state when the data is present the first time it was fetched on useEffect?为什么 React 的 useReducer 在第一次在 useEffect 上获取数据时返回空状态? 【发布时间】:2020-04-06 05:23:18 【问题描述】:

我正在使用 react hooks 和 contextAPI 开发一个简单的 MERN 堆栈 todo 应用程序,我使用 axios 从 mongodb 数据库中获取数据并设置 initialState 数组变量useEffect 来模拟 componentDidMount,然后将 initialState 用作 useReducer 的参数。我的问题是子组件没有收到 initialState 而是一个空数组,但是所有其他道具(例如调度和加载变量)都可以通过。为什么useReducer返回并清空状态数组?

父组件:

import React,  useEffect, useState, useReducer  from 'react';
import Header from './components/header/Header';
import Main from './components/main/Main';
import AppContext from './context/AppContext';
import axios from 'axios';
import './stylesheets/index.scss';

function App() 
  const [initialState, setInitialState] = useState([]);
  const [isError, setIsError] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  /* Fetch data */
  const fetchData = async () => 
    setIsError(false);
    setIsLoading(true);
    try 
      const response = await axios.get('/list');
      setInitialState(response.data);
     catch (error) 
      setIsError(true);
      console.log(`Unable to get: $error`);
    
    setIsLoading(false);
  ;

  /* Post new data */
  const postNewData = async (parameter) => 
    setIsError(false);
    try 
      const response = await axios.post('/list', parameter);
      console(response.data);
     catch (error) 
      setIsError(true);
      console.log(`Unable to post: $error`);
    
  ;

  /* Delete data */
  const deleteData = async (id) => 
    setIsError(false);
    try 
      const response = await axios.delete(`/list/$id`);
      console(response.data);
     catch (error) 
      setIsError(true);
      console.log(`Unable to delete: $error`);
    
  ;

  useEffect(() => 
    /* On load fetch data from the database */
    fetchData();
  , []);

  useEffect(() => 
    console.log(initialState);
  , [initialState]); 

  const appReducer = (state = initialState, action) => 
    switch (action.type) 
      case 'ADD_NEW_LIST':
        return postNewData(action.new_list);
      case 'DELETE_LIST':
        return deleteData(action.list_id);
      default:
        return state;
    
  ;

  const [state, dispatch] = useReducer(appReducer, initialState);

  return (
    <AppContext.Provider value= state, dispatch, isError, isLoading >
      <div className='App'>
        <Header />
        <Main />
      </div>
    </AppContext.Provider>
  );


export default App;

这是主组件中的子组件:

import React,  useContext, useEffect, useState  from 'react';
import AppContext from '../../context/AppContext';

function Listarea() 
  const  state, isError, isLoading, dispatch  = useContext(AppContext);

    console.log(state);
    console.log(isError);
    console.log(isLoading);

  return <div className='list-area'>list area here</div>;


export default Listarea;

这是 console.log 输出

如您所见,数据存在于 Parent 组件中,但不存在于子组件中,除了能够进入的其他 props。

【问题讨论】:

你发送 state 并尝试引用 appState @HagaiHarari 抱歉,这是一个错字(我已修复),我仍然遇到同样的错误。即使我在将其作为值分配给提供者之前 console.log 状态,它仍然是空数组。 【参考方案1】:

如果你更新你的 initialState 值,它不会改变你的 useReducer 的状态。

您可以简单地使用一个状态并在获取数据时更新该状态,您不需要 initialState 和 state,因此您可以删除 initialState。

const appReducer = (state = initialState, action) => 
    switch (action.type) 
      case 'SET_DATA':
        return action.data;
      case 'ADD_NEW_LIST':
        return postNewData(action.new_list);
      case 'DELETE_LIST':
        return deleteData(action.list_id);
      default:
        return state;
    
  ;

const [state, dispatch] = useReducer(appReducer, []);

const fetchData = async () => 
    setIsError(false);
    setIsLoading(true);
    try 
      const response = await axios.get('/list');
      dispatch( type: 'SET_DATA', data: response.data );
     catch (error) 
      setIsError(true);
      console.log(`Unable to get: $error`);
    
    setIsLoading(false);
  ;

【讨论】:

useReducer函数中是否允许使用空数组且不带reducer参数? 我的错!第一个参数应该是 appReducer,第二个是空数组

以上是关于为啥 React 的 useReducer 在第一次在 useEffect 上获取数据时返回空状态?的主要内容,如果未能解决你的问题,请参考以下文章

react中 useContext 和useReducer的使用

React Hook 高级用法

如何在 React 中使用 useReducer 更新嵌套对象?

在 React 中使用 useReducer 钩子过滤列表?

[React] When to useReducer instead of useState

React中useReducer的理解与使用