welldone-software / why-did-you-render

why-did-you-render by Welldone Software monkey patches React to notify you about potentially avoidable re-renders. (Works with React Native as well.)
https://www.npmjs.com/package/@welldone-software/why-did-you-render
MIT License
11.12k stars 199 forks source link

Detect WDYR running too late #247

Open jfairley opened 2 years ago

jfairley commented 2 years ago

I have an app that uses a lot of mainstream React libraries including react-router and react-redux. It's big so we also leverage React.lazy and React.Suspense.

I recently noticed dev errors from React around hook render ordering. You know the one, where React yells at you if you have a hook running conditionally. Well in my case, I was getting the errors, but I was confident that I wasn't running hooks conditionally.

After a lot of investigating, I found the issue to be a simple combination of why-did-you-render and React.lazy.

I don't propose to explain the reason for this issue, but I have come up with a simple-as-possible example to show it off.

https://github.com/jfairley/wdyr-lazy-bug

In this example, I have:

  1. why-did-you-render
  2. React.lazy
  3. a delayed render of a lazy component
    • The real use case here is waiting for app state to initialize before unleashing the rest of the app.

If I take away any of these 3 parts of the puzzle, the app renders without errors.

Realistically, the app doesn't always blow up, so simply disabling why-did-you-render unless explicitly needed to debug a dev scenario was the solution for me. I understand that the issue is some confluence of timing between the lazy import / initialization of why-did-you-render, the lazy import of components (via React.lazy), and obviously the intentional delay of rendering downstream components, but as I said, my app is complicated, so these things are immovable objects unfortunately.

Anyway, please have a look and thanks!

vzaidman commented 2 years ago

can you please try using a regular require rather than an import for the wdyr file?

jfairley commented 2 years ago

@vzaidman It works when I do it that way. Good point.

A note of value for the README in some fashion... I remember moving away from require() and the reason I did it was @typescript-eslint/no-var-requires. This is part of @typescript-eslint/recommended, so I imagine it's pretty common configuration for TypeScript + React users. I didn't realize I was breaking it when I did this.

Alternatively, is there any way why-did-you-render can detect when it's being initialized dangerously late and log a counter instruction? The nature of this error was very misleading, and it took me a while to figure out that (my configuration of) why-did-you-render was the issue.

vzaidman commented 2 years ago

is there any way why-did-you-render can detect when it's being initialized dangerously late and log a counter instruction?

It's a common problem indeed. I Guess we can add something that checks whether WDYR got initialized early enough.

The problem is that I can't think of a way to check this. I'll leave it as a wish.