You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React自行实现Redux时遭遇Uncaught TypeError错误求助

问题:Redux结合API获取数据时出现Uncaught TypeError: Cannot read properties of null (reading 'useState')错误

错误堆栈信息

Uncaught TypeError: Cannot read properties of null (reading 'useState')
at useState (react.development.js:1622:1)
at ApiReducer (ApiReducer.js:6:1)
at redux.js:468:1
at Array.forEach (<anonymous>)
at assertReducerShape (redux.js:466:1)
at combineReducers (redux.js:531:1)
at ./src/components/redux/reducers/CombineReducer.js (CombineReducer.js:4:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)

错误原因

  1. Reducer非法使用React Hooks:Redux的Reducer必须是纯函数,仅能接收state和action参数并返回新状态,不能调用useState等React Hooks。Hooks仅允许在React组件或自定义Hooks中执行,Reducer运行时不在React组件渲染周期内,无法找到对应上下文,因此触发useState读取null的错误。
  2. Reducer包含异步操作:Reducer内直接发起axios.get异步请求,违反了Redux Reducer的纯函数规则(不能有副作用、异步逻辑)。
  3. 状态处理逻辑错误:试图直接返回异步请求的Promise对象作为状态,不符合Redux通过action更新状态的工作流程。

解决方案

1. 重构Reducer(ApiReducer.js)

移除Hooks和异步逻辑,仅处理同步状态更新:

// ApiReducer.js
const initialState = {
  data: null,
  error: null,
  loading: false
};

const ApiReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'FETCH_START':
      return { ...state, loading: true, error: null };
    case 'FETCH_SUCCESS':
      return { ...state, loading: false, data: action.payload };
    case 'FETCH_ERROR':
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
};

export default ApiReducer;

2. 重构Action(action.js)

将异步请求移至thunk action中,请求完成后dispatch对应action更新状态:

// action.js
import axios from "axios";

export const tesla = () => {
  return async (dispatch) => {
    dispatch({ type: 'FETCH_START' });
    try {
      const response = await axios.get("https://newsapi.org/v2/everything?q=tesla&from=2022-07-17&sortBy=publishedAt&apiKey=b1e1719ca0724ff9bd9dab0645884e9a");
      dispatch({ type: 'FETCH_SUCCESS', payload: response.data });
    } catch (error) {
      dispatch({ type: 'FETCH_ERROR', payload: error.message });
    }
  };
};

export const business = () => {
  return async (dispatch) => {
    dispatch({ type: 'FETCH_START' });
    try {
      const response = await axios.get("https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=b1e1719ca0724ff9bd9dab0645884e9c");
      dispatch({ type: 'FETCH_SUCCESS', payload: response.data });
    } catch (error) {
      dispatch({ type: 'FETCH_ERROR', payload: error.message });
    }
  };
};

3. 修正组件逻辑(Rexercise.js)

移除组件内的useState,直接通过useSelector获取Redux状态:

// Rexercise.js
import React from "react";
import { useSelector, useDispatch } from 'react-redux';
import { actions } from "./redux";

const Rexercise = () => {
  const { data, error, loading } = useSelector(state => state.value);
  const dispatch = useDispatch();

  const Tesla = () => {
    dispatch(actions.tesla());
  };
  const Business = () => {
    dispatch(actions.business());
  };

  return (
    <div className="container">
      <h1>Hello World</h1>
      <button className="btn btn-primary" onClick={Tesla}>Tesla</button>
      <button className="mx-2 btn btn-success" onClick={Business}>Business</button>

      {loading && <div>加载中...</div>}
      {error && <div className="text-danger">请求错误:{error}</div>}
      {data && (
        <div className="article text-primary">
          <h3>新闻总数:{data.totalResults}</h3>
          <ul>
            {data.articles.slice(0, 5).map((article, index) => (
              <li key={index}>{article.title}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default Rexercise;

4. 简化Store配置(可选)

Redux Toolkit的configureStore默认已包含redux-thunk middleware,无需手动添加,同时修正拼写错误:

// Store.js
import { configureStore } from "@reduxjs/toolkit";
import reducers from "../reducers/CombineReducer";

const Store = configureStore({
  reducer: reducers,
  preloadedState: {}
});

export default Store;

内容的提问来源于stack exchange,提问作者piyush shende

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 03:24:39