Why does react hook throw the act error when used with fetch api?

大兔子大兔子 提交于 2020-02-03 05:02:09

问题


I keep getting Warning: An update to App inside a test was not wrapped in act(...). in my test suite whenever I make an API request and update the state.

I'm making use of react-testing-library. I also tried using ReactDOM test utils, got the same result. One other thing I tried was wrapping the container in act, still got the same result.

Please note that: My App works and my test passes. I just need to know what I was doing wrong or if it's a bug in the react-dom package that's making that error show up. And it's bad to mock the console error and mute it.

global.fetch = require('jest-fetch-mock');

it('should clear select content item', async () => {
    fetch.mockResponseOnce(JSON.stringify({ results: data }));

    const { container } = render(<App />);

    const content = container.querySelector('.content');

    await wait();

    expect(content.querySelectorAll('.content--item').length).toBe(2);
});

Here's the hook implementation:

const [data, setData] = useState([]);
const [error, setError] = useState('');

const fetchInitData = async () => {
    try {
        const res = await fetch(API_URL);
        const data = await res.json();

        if (data.fault) {
            setError('Rate limit Exceeded');
        } else {
            setData(data.results);
        }
    } catch(e) {
        setError(e.message);
    }
};

useEffect(() => {
    fetchInitData();
}, [isEqual(data)]);

回答1:


It's a known problem, check this issue in Github https://github.com/kentcdodds/react-testing-library/issues/281




回答2:


To get rid of the act() warning you need to make sure your promises resolve synchronously. You can read here how to do this.

Summary:

The solution for this is a bit involved:

  • we polyfill Promise globally with an implementation that can resolve promises 'immediately', such as promise
  • transpile your javascript with a custom babel setup like the one in this repo
  • use jest.runAllTimers(); this will also now flush the promise task queue



回答3:


I had this problem and gave up using wait and async instead used jest faketimers and so on, so your code should be something like this.

global.fetch = require('jest-fetch-mock');

it('should clear select content item', /*async */ () => {
    jest.useFakeTimers();
    fetch.mockResponseOnce(JSON.stringify({ results: data }));

    const { container } = render(<App />);

    const content = container.querySelector('.content');

    // await wait();
    act(() => {
      jest.runAllTimers();
    });

    expect(content.querySelectorAll('.content--item').length).toBe(2);
});


来源:https://stackoverflow.com/questions/54748942/why-does-react-hook-throw-the-act-error-when-used-with-fetch-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!