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

React Native+Redux Toolkit异步API调用类型及Hook调用错误

问题解决方案

错误1:类型错误 AsyncThunkAction<any, void, AsyncThunkConfig> 无法赋值给 AnyAction

原因

react-redux 原生的 useDispatch() 返回的是 Dispatch<AnyAction> 类型,而 createAsyncThunk 生成的异步 action 属于 AsyncThunkAction 类型,两者类型不兼容。

解决方法

使用你在 hooks.ts 中定义的自定义类型化钩子 useAppDispatch,替换原生的 useDispatch。


错误2:无效钩子调用 Invalid hook call. Hooks can only be called inside of the body of a function component

原因

你在 splash.tsx 中混用了原生钩子和自定义类型化钩子,导致类型和调用逻辑冲突(虽然你的钩子调用位置符合规则,但类型不匹配会间接引发此类错误提示)。

解决方法

统一使用 hooks.ts 导出的 useAppSelector 和 useAppDispatch,替换原生的 useSelector/useDispatch。


修改后关键代码

1. 更新 splash.tsx

import React from "react";
import { View, TouchableOpacity, Text, SafeAreaView, Image } from "react-native";
import { styles } from "../../utility/styles/styles";
import { selectStatus } from "../../slices/todo/todoSlice";
// 替换原生钩子为自定义类型化钩子
import { useAppSelector, useAppDispatch } from "../../hooks/hooks";
import { getHomeData } from "../../actions/get_home_json";

function Splash({ navigation}: {navigation : any}) {
  // 使用自定义钩子
  const status = useAppSelector(selectStatus);
  const dispatch = useAppDispatch();
  const handleClick = () => {dispatch(getHomeData())};

  return (
    <SafeAreaView>
      <View >
        <Image source={require('../../resources/images/gif/splash.gif')} style={styles.image} />
        <TouchableOpacity style={styles.button} onPress={handleClick}>
          <Text> Push Home</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

export default Splash;

2. 补充 todoSlice.ts 的异步 action 处理

你当前的切片只处理了 fetchTodos,需要添加 getHomeData 的状态更新逻辑:

// todoSlice.ts
import {Todo} from "../../models/todo"
import { RootState } from "../../store/store";
import { createSlice } from "@reduxjs/toolkit";
import { fetchTodos } from "../../actions/fetchTodos";
import { getHomeData } from "../../actions/get_home_json";

// 扩展状态类型,添加首页数据字段
type TodosState = {
  status: "loading" | "idle";
  error: string | null;
  list: Todo[];
  homeData: any; // 建议替换为实际的首页数据类型
};

const initialState: TodosState = {
  list: [],
  error: null,
  status: "idle",
  homeData: null,
};

export const selectStatus = (state: RootState) => state.todos.status;
export const selectHomeData = (state: RootState) => state.todos.homeData;

export const todosSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    // 原有fetchTodos处理逻辑...
    builder.addCase(fetchTodos.pending, (state) => {
      state.status = "loading";
      state.error = null;
    });
    builder.addCase(fetchTodos.fulfilled, (state, { payload }) => {
      state.list.push(...payload);
      state.status = "idle";
    });
    builder.addCase(fetchTodos.rejected, (state, { payload }) => {
      if (payload) state.error = payload.message;
      state.status = "idle";
    });

    // 新增getHomeData的状态处理
    builder.addCase(getHomeData.pending, (state) => {
      state.status = "loading";
      state.error = null;
    });
    builder.addCase(getHomeData.fulfilled, (state, { payload }) => {
      state.homeData = payload;
      state.status = "idle";
    });
    builder.addCase(getHomeData.rejected, (state, action) => {
      state.error = action.error.message || "获取首页数据失败";
      state.status = "idle";
    });
  },
});

export default todosSlice.reducer

3. 优化 getHomeData 的类型定义(可选但推荐)

避免使用 any,定义明确的返回类型:

// 定义首页数据类型
export type HomeData = {
  // 根据API返回结构定义字段
  id: string;
  title: string;
  // ...其他字段
};

export const getHomeData = createAsyncThunk<HomeData, void>(
  'actions/getHomeData', 
  async () =>{
    const response = await API.get(configAEM.apis.home);
    const data = await response.json();
    return data;
  }
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 05:17:08