TypeScript中Generator函数(yield)无法配合自定义Hook使用怎么办?
问题分析与解决方案
核心问题
React Hooks 只能在React函数组件或自定义React Hook函数的顶层调用,而你用的calling是Redux-Saga的Generator副作用函数,完全不属于React组件/Hook环境,直接调用useCustom会触发Hook规则报错;你封装的普通函数Custom里调用useCustom同样违反规则,导致Hook逻辑未正常执行,字符串替换功能失效。
解决思路
将useCustom中字符串替换的核心逻辑从Hook中抽离成独立工具函数,既可以在React Hook中复用,也能直接在Saga的Generator函数里调用(无需依赖React环境)。
步骤1:抽离核心替换逻辑
假设原useCustom内部是读取JSON文件实现字符串替换,把这部分逻辑单独提取:
// utils/customString.ts import { Stringable } from '../types'; // 替换为你实际的JSON文件路径或动态读取逻辑 const customLocaleData = require('../locales.json'); export const getCustomString = (key: string, replace?: Stringable[]): string => { // 获取对应key的替换文本,未找到则返回原key const targetText = customLocaleData[key] || key; // 处理占位符替换(示例:{0}、{1}格式) if (!replace?.length) return targetText; return targetText.replace(/\{(\d+)\}/g, (_, index) => { const replacement = replace[Number(index)]; return replacement != null ? String(replacement) : _; }); };
步骤2:重构原useCustom Hook
让Hook复用抽离的工具函数,保留React环境下的使用能力:
// hooks/useCustom.ts import { Stringable } from '../types'; import { getCustomString } from '../utils/customString'; export const useCustom = () => { // 如果原Hook有依赖React状态/上下文的逻辑(比如语言切换监听),可保留在此处 // 示例:const locale = useContext(LocaleContext); return (key: string, replace?: Stringable[]): string => { return getCustomString(key, replace); // 若有上下文依赖,可改为:return getCustomString(key, replace, locale); }; };
步骤3:在Generator函数中直接使用工具函数
现在可以在calling里直接调用工具函数,完全避开Hook规则限制:
import { getCustomString } from './utils/customString'; export function* calling(action: any) { try { const message = getCustomString('Template applied.'); yield call(status, message, StatusType.success); } catch (e) { yield put(getFail(e)); } }
特殊场景处理(若原Hook依赖React上下文)
如果原useCustom依赖React上下文(比如多语言切换的LocaleContext),可将上下文状态同步到Redux store,在Saga中通过select获取:
// 在Saga中获取Redux存储的语言状态 import { select } from 'redux-saga/effects'; import { getCurrentLocale } from './store/selectors'; // 自定义selector export function* calling(action: any) { try { const locale = yield select(getCurrentLocale); const message = getCustomString('Template applied.', [], locale); // 调整工具函数支持locale参数 yield call(status, message, StatusType.success); } catch (e) { yield put(getFail(e)); } }
内容的提问来源于stack exchange,提问作者Cesar Ochoa
相关产品推荐
相关产品推荐

