【问题标题】:Why does this custom React hook using useContext useEffect and setInterval fail in test为什么这个使用 useContext useEffect 和 setInterval 的自定义 React 钩子在测试中失败
【发布时间】:2019-08-24 20:45:32
【问题描述】:

我正在尝试测试一个自定义的 React 钩子。

我不明白为什么 setInterval 中的回调函数运行时没有使用新的上下文。

@testing-library/react 不存在问题,因为它可以使用新的上下文重新渲染。很可能在 useContext、useEffect 和 setInterval 之间发生了一些事情,但我不知道是什么。

自定义 React 钩子'useCustomContext.ts':

import { useContext, useEffect, useRef, createContext } from 'react';

export const CustomContext = createContext('');

export const useValueFromContext = function() {
  const context = useContext(CustomContext);
  const ref = useRef('');

  function getContext() {
    return context;
  }

  useEffect(() => {
    ref.current = getContext();
    const interval = setInterval(() => {
      ref.current = getContext();
    }, 1000);
    return () => clearInterval(interval);
  }, []);

  return ref.current;
};

export default useValueFromContext;

测试“useCustomContext.test.tsx”失败:

import React from 'react';
import { useValueFromContext, CustomContext } from './useCustomContext';
import { render } from '@testing-library/react';

test('Should return value from most recently provided context', async () => {
  const Component = () => {
    const value = useValueFromContext();
    return <span data-testid="context">{value}</span>;
  };

  const { getByTestId, rerender } = render(
    <CustomContext.Provider value="a">
      <Component />
    </CustomContext.Provider>,
  );

  rerender(
    <CustomContext.Provider value="b">
      <Component />
    </CustomContext.Provider>,
  );

  await new Promise(resolve => {
    setTimeout(() => {
      rerender(
        <CustomContext.Provider value="b">
          <Component />
        </CustomContext.Provider>,
      );
      resolve();
    }, 2000);
  });

  expect(getByTestId('context').textContent).toBe('b');
});

输出:

Should return value from most recently provided context

    expect(received).toBe(expected) // Object.is equality

    Expected: "b"
    Received: "a"

【问题讨论】:

    标签: reactjs react-hooks react-testing-library


    【解决方案1】:

    我发现了问题。我必须像这样向 useEffect 依赖项添加上下文:

      useEffect(() => {
        ref.current = getContext();
        const interval = setInterval(() => {
          ref.current = getContext();
        }, 1000);
        return () => clearInterval(interval);
      }, [context]);
    

    【讨论】:

      猜你喜欢
      • 2020-02-19
      • 2021-12-12
      • 2020-01-26
      • 2021-04-17
      • 2021-10-22
      • 2021-12-26
      • 1970-01-01
      • 2021-09-10
      • 2021-12-14
      相关资源
      最近更新 更多