question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

query / test starts after two rerenders of the view

See original GitHub issue

Describe the bug

Hi, I’m not sure if it’s a bug or a question, but it feels for me that it is working the wrong way. I want to test a simple thing in one of my views, which is a loader appearance.

View looks like this:

export const TheView: React.FC<Props> = (props) => {
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
        setIsLoading(true);
        performWhateverPromiseOrRequest()
          .finally(() => {
            setIsLoading(false);
          });
      }
    }
  }, []);

  return (
    <View style={styles.container}>
      {isLoading && <View testID="activityIndicator" style={styles.activityIndicator} />}
{...theRestOfTheView}
    </View>
  );
};

And the test looks like this:

it('should show the loader at the beginning if coordinates arent defined', async () => {
   // mocks

    const { findByTestId, queryByTestId } = render({
      initialState
    });

    console.log('here');

    const loader = queryByTestId('activityIndicator');

    await waitFor(() => expect(loader).not.toBeNull());
  });

Please take a look at the console logs both in the view and the test. The result I get from them is:

console.log false

console.log true

console.log here

console.log true

console.log true

console.log false

It looks like the view is being rerendered twice before the query / test even begins. This is the snippet from the render.js file from the lib:

function render(component, {
  wrapper: Wrapper,
  createNodeMock
} = {}) {
  const wrap = innerElement => Wrapper ? /*#__PURE__*/React.createElement(Wrapper, null, innerElement) : innerElement;

  const renderer = renderWithAct(wrap(component), createNodeMock ? {
    createNodeMock
  } : undefined);
  const update = updateWithAct(renderer, wrap);
  const instance = renderer.root;
  (0, _cleanup.addToCleanupQueue)(renderer.unmount);
  return { ...(0, _getByAPI.getByAPI)(instance),
    ...(0, _queryByAPI.queryByAPI)(instance),
    ...(0, _findByAPI.findByAPI)(instance),
    ...(0, _a11yAPI.a11yAPI)(instance),
    update,
    container: instance,
    rerender: update,
    // alias for `update`
    unmount: renderer.unmount,
    toJSON: renderer.toJSON,
    debug: debug(instance, renderer)
  };
}

and it seems like I’m right - I can see render and update methods called.

Expected behavior

I’d like the “hear” console.log to appear before any other console.log so that I can actually wait for things that happen from the beginning of the tested component’s lifecycle.

Steps to Reproduce

Just implement a similar code, put the console logs in the same places and see what happens.

Versions

@testing-library/react-native: ^7.2.0 => 7.2.0 react: 17.0.2 => 17.0.2 react-native: 0.67.2 => 0.67.2 react-test-renderer: 17.0.2 => 17.0.2

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
wmatyjanomtekcommented, Feb 22, 2022

@pierrezimmermannbam So I think I didn’t catch that properly. Understood. Thank you for your time (again) and explanations. 😉

0reactions
pierrezimmermannbamcommented, Feb 22, 2022

@wmatyjanomtek yes I think it doesn’t matter, it is shown instantaneously to the user. All synchronous code run in useEffects will be completed before your first query so there’s no need to wait for them to be finished, you should only use waitFor when promises are involved. Also if there are timeouts then you should use jest fake timers api

In addition to what I said earlier, here is the description of the act util from react-test-renderer

Wrap any code rendering and triggering updates to your components into act() calls.

Ensures that the behavior in your tests matches what happens in the browser more closely by executing pending useEffects before returning. This also reduces the amount of re-renders done.

The act util ensures that all useEffects will be run when udpating a component/hook state in a test to match better the user’s experience so it’s definitely the intended behavior

Read more comments on GitHub >

github_iconTop Results From Across the Web

Component infinite Re-renders, when passing new Date ...
The component which contains <Query /> keeps re-rendering when the variables are provided with new Date().toISOString() to startsAt_gte Prisma ...
Read more >
React Query Render Optimizations - TkDodo's blog
An advanced guide to minimize component re-renderings when using React Query.
Read more >
How to identify and resolve wasted renders in React
Let's say some data changes in Component 2 in the above picture, and that data has been passed from R to B and...
Read more >
How to solve too many re-renders error in ReactJS?
I've built 2 components of React in this code. One is a part of the greeting, and the other is the app component....
Read more >
How to check if your component rerendered - and why!
This can work fine at the beginning - but what if you want to answer bigger ... Using React DevTools to highlight what...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found