为什么开玩笑不调用useEffect挂钩内的函数?

时间:2020-03-15 09:53:03

标签: reactjs jestjs

我有一个异步功能setInitialData,在应用程序useEffect的{​​{1}}挂钩中调用了该函数。我想测试该函数已被调用。该测试失败。为什么?

provider

仅提供更多上下文,我有一个自定义const dispatch = jest.fn(); const state = {...} jest.mock('../context/actions', () => ({ setInitialData: jest.fn(), })); test('setInitialData fn is called in useEffect hook in the provider', () => { const {debug} = render(<CurrencyExchange />, {state, dispatch}); expect(setInitialData).toHaveBeenCalled(); }); Expected number of calls: >= 1 Received number of calls: 0 函数,因此我的组件位于提供程序中:

render

实际的Provider实现如下:

const customRender = (ui, {state = {}, dispatch = () => undefined, ...options} = {}) => {
  function Wrapper({children, props}) {
    return (
      <CurrencyStateContext.Provider value={state} {...props}>
        <CurrencyDispatchContext.Provider value={dispatch}>
          <ThemeProvider theme={theme}>
            <CSSReset />
            {children}
          </ThemeProvider>
        </CurrencyDispatchContext.Provider>
      </CurrencyStateContext.Provider>
    );
  }
  return render(ui, {wrapper: Wrapper, ...options});
};
export {customRender as render};

--- 编辑 ---

好的。我有。

function CurrencyProvider({children}: CurrencyProviderProps): JSX.Element {
  const [state, dispatch] = React.useReducer<React.Reducer<CurrencyState, Action>>(reducer, initialState);

  React.useEffect(() => {
    setInitialData(dispatch);
  }, []);

进入 React.useEffect(() => { setInitialData(dispatch); }, []); 组件,现在我得到了预期的断言。 但是,仍然有人可以向我解释为什么CurrencyExchange直接位于应用程序提供商中时没有被调用吗?

1 个答案:

答案 0 :(得分:0)

useEffect是异步的,因此您必须使用act等待它。 useLayoutEffect是同步的

等待useEffect,您可以尝试

import { act } from 'react-dom/test-utils'

test('setInitialData fn is called in useEffect hook in the provider', () => {
  let debug
  await act(async () => { 
    debug = render(<CurrencyExchange />, {state, dispatch}).debug;
  })

  expect(setInitialData).toHaveBeenCalled();
});