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

如何将Hook中的状态存入Redux Toolkit Store?

问题分析与解决方案

核心错误原因

你在createAsyncThunk的异步函数里直接调用了useBalances这个React Hook,这违反了React Hook的使用规则:Hook只能在React函数组件的顶层、或者自定义Hook的顶层调用,绝对不能在普通异步函数、循环、条件判断里调用。这直接导致React抛出错误,触发了thunk的rejected状态,所以你的Redux store里error被设为true。

另外你的thunk逻辑还有两个小问题:

  • forEach里的return不会终止循环也不会返回值,应该用find来定位目标余额项
  • 没有处理异步等待逻辑,useBalances内部是异步请求,但你同步拿data根本获取不到异步返回的结果

解决方案一:组件内使用Hook后同步到Redux

既然组件里调用useBalances是正常的,那可以在组件中拿到数据后,dispatch一个普通action把数据存入store:

1. 新增同步action

// 在accounts slice中新增同步action
export const setAccountBalance = createAction<number>("accounts/setBalance");

2. 更新reducer处理同步action

export const accountsReducer = createReducer(initialState, (builder) => {
  builder
    .addCase(getAccounts.pending, (state) => {
      state.pending = true;
    })
    .addCase(getAccounts.fulfilled, (state, { payload }) => {
      state.pending = false;
      state.amount = payload.amount;
    })
    .addCase(getAccounts.rejected, (state) => {
      state.pending = false;
      state.error = true;
    })
    // 新增同步action的处理逻辑
    .addCase(setAccountBalance, (state, action) => {
      state.amount = action.payload;
    });
});

3. 在组件中使用Hook并同步数据

const dispatch = useAppDispatch();
const { amount, pending, error } = useAppSelector(accountsSelector);
const account = "name";
const { data, isFetching } = useBalances(account);

// 当data更新时,自动同步到Redux
useEffect(() => {
  if (data) {
    const targetBalance = data.find(balance => balance.title === "name");
    if (targetBalance) {
      dispatch(setAccountBalance(Number.parseInt(targetBalance.amount)));
    }
  }
}, [data, dispatch]);

return (
  <div>
    {isFetching && <p>Fetching balances...</p>}
    {amount && <p>redux amount: {amount}</p>}
    {error && <p>Error occurred!</p>}
  </div>
);

解决方案二:直接在thunk中调用原始API

如果一定要在Redux thunk里获取数据,你需要找到useBalances内部实际调用的API请求函数(比如fetchBalances(account)),而非直接使用Hook。假设useBalances内部的原始API函数是这样的:

// 示例:useBalances内部封装的API请求函数
export const fetchBalances = async (account: string) => {
  const res = await fetch(`/api/balances/${account}`);
  return res.json();
};

那你可以修改thunk直接调用这个API:

修正后的thunk代码

export const getAccounts = createAsyncThunk("accounts/getBalance", async () => {
  const account = "name";
  try {
    // 直接调用原始API,避免使用Hook
    const data = await fetchBalances(account);
    const targetBalance = data.find(balance => balance.title === "name");
    if (targetBalance) {
      return { amount: Number.parseInt(targetBalance.amount) };
    }
  } catch (e) {
    // 抛出错误,让thunk进入rejected状态
    throw e;
  }
  return { amount: 0 };
});

这样就能避免在thunk中调用Hook的违规操作,同时正确处理异步请求。


额外注意点

  • 非组件/非自定义Hook的场景绝对不能调用React Hook,这是硬性规则
  • 查找单个元素时,find比forEach更合适,forEach无法通过return返回结果
  • 异步操作必须加await,否则无法获取异步返回的数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 00:45:36