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

能否从ThunkAction返回unsubscribeSnapshot等取消订阅引用?

问题:能否从Redux Thunk Action返回订阅取消函数的引用?

请问是否可以像以下示例这样,从ThunkAction返回unsubscribeSnapshot的引用?

export const someFetchAction = () => async (dispatch: Dispatch, getState: GetState) => {
  let unsubscribeAuth: UnsubscribeAuth | null = null;
  let unsubscribeSnapshot: UnsubscribeSnapshot | null = null;

  try {
    // 监听认证状态变化
    unsubscribeAuth = getAuth().onAuthStateChanged(user => {
      // 检查用户是否已认证
    });

    // 监听快照更新
    unsubscribeSnapshot = onSnapshot(queryRef, (docsSnapshot) => {
      // 分发数据并将loaded设为true
    })

    return {
      unsubscribe: () => {
        if (unsubscribeAuth && unsubscribeSnapshot) {
          unsubscribeAuth();
          unsubscribeSnapshot();
        }
      }
    }

  catch(error) {
    // 分发错误并将error标志设为true
    if (unsubscribeAuth && unsubscribeSnapshot) {
      unsubscribeAuth();
      unsubscribeSnapshot();
    }
  }
}

我尝试在React的useEffect中调用该方法:

const { loaded } = useSelector(state => ({
  loaded: state.fireReducer.loaded,
}))

const { someFetchAction } = useActions({
  someFireAction: fireActions.someFireAction,
});

useEffect(() => {
  let actionRef;
  if (!loaded) {
    actionRef = someFireAction();
  }

  return () => {
    actionRef.unsubscribe();
  }
}, [loaded])

回答:

这种做法是可行的,但需要修正几个关键问题才能正常运行:

  1. 处理异步Thunk的返回值
    你的Thunk是async函数,调用someFireAction()后返回的是一个Promise,而非直接拿到包含unsubscribe的对象。当前代码直接访问actionRef.unsubscribe()会报错,需要改为异步获取返回值:
useEffect(() => {
  let unsubscribeFn;
  if (!loaded) {
    someFireAction().then(result => {
      unsubscribeFn = result?.unsubscribe;
    });
  }

  return () => {
    if (unsubscribeFn) {
      unsubscribeFn();
    }
  }
}, [loaded])
  1. 空值安全检查
    当loaded初始值为true时,actionRef会是undefined,此时清理函数调用actionRef.unsubscribe()会抛出错误,必须先判断函数是否存在再执行。

  2. Thunk内部的订阅完整性
    确保onAuthStateChanged和onSnapshot的订阅函数都能被正确赋值,避免出现其中一个订阅成功、另一个失败时,漏取消已成功的订阅(当前代码的try/catch已经处理了这种情况,无需修改)。

  3. TypeScript类型优化(可选)
    如果使用TypeScript,需要给Thunk的返回值定义明确类型,避免类型报错:

import { ThunkAction, AnyAction } from '@reduxjs/toolkit';
import { RootState } from '../store';

type UnsubscribeFn = () => void;
type ThunkReturn = Promise<{ unsubscribe: UnsubscribeFn } | undefined>;

export const someFetchAction = (): ThunkAction<ThunkReturn, RootState, unknown, AnyAction> => async (dispatch, getState) => {
  // 原有逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:52:51