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

如何用React Testing Library的renderHook测试嵌套Context?遇result.current未定义

测试React嵌套Context时result.current为undefined的排查与解决

问题重现

我在用React Testing Library的renderHook测试嵌套Context时遇到了问题,测试代码如下:

import React, { FC, useEffect, useMemo, useState } from 'react';
import { renderHook, waitFor } from '@testing-library/react';

interface PropsCtx {
  input: string;
  myval: string;
  setMyVal: React.Dispatch<React.SetStateAction<string>>;
}
const placeholder: PropsCtx = {
  input: '',
  myval: '',
  setMyVal: (prev) => prev
};
const CTX = React.createContext<PropsCtx>(placeholder);
interface PropsProvider {
  input: string;
  children: React.ReactNode;
}
const MyProvider: FC<PropsProvider> = ({ children, input }) => {
  const [myval, setMyVal] = useState<PropsCtx['myval']>(placeholder.myval);
  const value = useMemo<PropsCtx>(() => ({ input, myval, setMyVal }), [input, myval, setMyVal]);
  return <CTX.Provider value={value}>{children}</CTX.Provider>;
};

const Wrapper: FC<PropsProvider> = ({ input, children }) => (
  <MyProvider input={input}>{children}</MyProvider>
);

interface PropsUse {
  newinput: string;
}
const useFromProvider= ({ newinput }: PropsUse) => {
  const { input, myval, setMyVal } = React.useContext(CTX);
  useEffect(() => {
    setTimeout(() => {
      setMyVal(newinput);
    }, 1000)
  }, []);

  return { input, myval, setMyVal };
};
describe('useFromProvider', () => {
  it('should return context results', async () => {
    const wrapper = () => <Wrapper input={'hello'}><div>content</div></Wrapper>
    const { result } = renderHook(
      () =>
        useFromProvider({newinput: 'goodbye'}),
      { wrapper }
    );

    expect((result as any).current.input).toBeTruthy();
  });
});

运行测试时出现错误:

错误
result.current === undefined

问题原因

问题出在renderHook的wrapper函数上:你当前的wrapper硬编码了<div>content</div>作为子元素,没有接收renderHook传入的children参数(也就是包装了测试hook的组件),也没有将其传递给Wrapper组件。

这导致useFromProvider根本没有被渲染在MyProvider的Context范围内,甚至可能完全没有被执行,最终result.current返回undefined。

修复方案

  1. 修正wrapper函数:让它接收children参数,并将其传递给Wrapper组件,确保测试的hook被正确包裹在Context Provider中。
  2. 补充依赖项:给useEffect添加缺失的newinput依赖,避免ESLint警告。
  3. 完善断言逻辑:利用waitFor处理异步的setTimeout操作,确保断言在状态更新完成后执行,同时去掉any断言,利用TypeScript的类型检查。

完整修正代码

import React, { FC, useEffect, useMemo, useState } from 'react';
import { renderHook, waitFor } from '@testing-library/react';

interface PropsCtx {
  input: string;
  myval: string;
  setMyVal: React.Dispatch<React.SetStateAction<string>>;
}
const placeholder: PropsCtx = {
  input: '',
  myval: '',
  setMyVal: (prev) => prev
};
const CTX = React.createContext<PropsCtx>(placeholder);
interface PropsProvider {
  input: string;
  children: React.ReactNode;
}
const MyProvider: FC<PropsProvider> = ({ children, input }) => {
  const [myval, setMyVal] = useState<PropsCtx['myval']>(placeholder.myval);
  const value = useMemo<PropsCtx>(() => ({ input, myval, setMyVal }), [input, myval, setMyVal]);
  return <CTX.Provider value={value}>{children}</CTX.Provider>;
};

const Wrapper: FC<PropsProvider> = ({ input, children }) => (
  <MyProvider input={input}>{children}</MyProvider>
);

interface PropsUse {
  newinput: string;
}
const useFromProvider = ({ newinput }: PropsUse) => {
  const { input, myval, setMyVal } = React.useContext(CTX);
  useEffect(() => {
    setTimeout(() => {
      setMyVal(newinput);
    }, 1000);
  }, [newinput]); // 补充依赖项

  return { input, myval, setMyVal };
};
describe('useFromProvider', () => {
  it('should return context results and update myval asynchronously', async () => {
    // 修正wrapper,接收children并传递
    const wrapper = ({ children }: { children: React.ReactNode }) => (
      <Wrapper input={'hello'}>{children}</Wrapper>
    );
    const { result } = renderHook(
      () => useFromProvider({ newinput: 'goodbye' }),
      { wrapper }
    );

    // 初始状态断言
    expect(result.current.input).toBe('hello');
    expect(result.current.myval).toBe('');

    // 等待异步更新完成
    await waitFor(() => {
      expect(result.current.myval).toBe('goodbye');
    });
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:24:59