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

React Native使用Redux调用API时出现Invalid Hook Call错误

React Native + Redux 无效Hook调用错误排查与修复

错误信息

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

This error is located at:
    in ComplaintsMenu (created by HomePage)
    in RCTView (created by View)
    in View (created by HomePage)
    in RCTView (created by View)
    in View (created by HomePage)
    in HomePage (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by CardContainer)
    in RCTView (created by View)
    in View (created by CardContainer)
    in RCTView (created by View)
    in View (created by CardContainer)
    in RCTView (created by View)
    in View
    in CardSheet (created by Card)
    in RCTView (created by View)
    in View (created by AnimatedComponent)
    in AnimatedComponent
    in AnimatedComponentWrapper (created by PanGestureHandler)
    in PanGestureHandler (created by PanGestureHandler)
    in PanGestureHandler (created by Card)
    in RCTView (created by View)
    in View (created by AnimatedComponent)
    in AnimatedComponent
    in AnimatedComponentWrapper (created by Card)
    in RCTView (created by View)
    in View (created by Card)
    in Card (created by CardContainer)
    in CardContainer (created by CardStack)
    in RNSScreen (created by AnimatedComponent)
    in AnimatedComponent
    in AnimatedComponentWrapper (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by MaybeScreen)
    in MaybeScreen (created by CardStack)
    in RNSScreenContainer (created by ScreenContainer)
    in ScreenContainer (created by MaybeScreenContainer)
    in MaybeScreenContainer (created by CardStack)
    in RCTView (created by View)
    in View (created by Background)
    in Background (created by CardStack)
    in CardStack (created by HeaderShownContext)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by SafeAreaInsetsContext)
    in SafeAreaProviderCompat (created by StackView)
    in RNGestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by StackView)
    in StackView (created by StackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by StackNavigator)
    in StackNavigator (created by App)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by App)
    in RCTView (created by View)
    in View (created by SafeAreaWrap)
    in SafeAreaWrap (created by App)
    in Provider (created by App)
    in App (created by withDevTools(App))
    in withDevTools(App)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)

Reducer代码

export function complaintReducer(state = initalComplaintsFormState, action) {
  switch (action.type) {
    //...other cases

    case GET_COMPLAINT_LIST:
      return { ...state, complaintList: action.payload };
      
    default:
      return state;
  }
}

ComplaintsMenu组件代码

//...other imports

import { useSelector, useDispatch } from "react-redux";
import { getComplaintList } from "../Redux/Actions";

export default function ComplaintsMenu() {

  const { ComplaintList } = useSelector((state) => state.complaintReducer);
  const dispatch = useDispatch;


// 我认为问题出在这里,因为dispatch函数(钩子?)在useEffect钩子中被调用,但我不清楚具体原因,也不知道如何实现需求,我是跟着下方的YouTube教程做的

useEffect(() => {  
dispatch(getComplaintList());
}, []);

return (
  <FlatList
    data={ComplaintList}
    renderItem={({ item }) => (
      <ComplaintCard
        key={item.complaint_id}
        title={item.issue}
        status={item.status}
      />
     )}
   />
);

依赖版本

{
"name": "poll-app",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@expo-google-fonts/inter": "^0.2.2",
"@expo/webpack-config": "^0.17.2",
"@react-navigation/native": "^6.1.3",
"@react-navigation/stack": "^6.3.12",
"expo": "~47.0.12",
"expo-status-bar": "~1.4.2",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.5",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-web": "~0.18.9",
"react-redux": "^8.0.5",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"eslint-plugin-react-hooks": "^4.6.0"
},
"private": true
}

已尝试操作

  • 重新安装react-redux和redux,执行npm update
  • 检查React版本一致性,确认所有依赖使用相同React版本

问题根源与修复方案

  1. Hook调用错误:useDispatch是React-Redux提供的Hook,必须以函数形式调用才能获取到dispatch方法,你的代码中遗漏了括号:
// 错误写法
const dispatch = useDispatch;

// 正确写法
const dispatch = useDispatch();
  1. 字段名不匹配:Reducer中定义的字段是complaintList(小写开头),但组件中使用ComplaintList(大写开头),会导致无法获取到状态数据,同步字段名即可:
// 正确的状态获取写法
const { complaintList } = useSelector((state) => state.complaintReducer);

// FlatList对应修改
<FlatList
  data={complaintList}
  renderItem={({ item }) => (
    <ComplaintCard
      key={item.complaint_id}
      title={item.issue}
      status={item.status}
    />
  )}
/>
  1. 异步Action检查:如果getComplaintList是请求后端API的异步Action,需确保它是符合Redux-Thunk规范的函数,示例如下:
export const getComplaintList = () => async (dispatch) => {
  try {
    // 替换为你的后端API地址
    const response = await fetch('https://your-api-url/complaints');
    const data = await response.json();
    dispatch({ type: GET_COMPLAINT_LIST, payload: data });
  } catch (error) {
    console.error('获取投诉列表失败:', error);
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:45:45