mohebifar / react-native-copilot

Step-by-step walkthrough tooltip for your react native app
MIT License
2.24k stars 407 forks source link

120 rerenders when I wrap my component in copilot. #202

Open davidfloegel opened 4 years ago

davidfloegel commented 4 years ago

Hi there,

so sorry for not using the template but this is more a question than anything.

I'm using the copilot HOC as described in the README. However, when I do that my component re-renders anywhere between 107 and 120 times every single time I call it..

I'm using start() and I'm calling that on mount. (incase that's important to know)

That doesn't seem very performant and also blocks up my entire UI thread and slows down animations. Is there any way around or to change that?

Cheers

pribeh commented 3 years ago

We're using this library and have noticed dips in performance. I'll check to see if I get the same results.

ronakjani123 commented 2 years ago

@davidfloegel Me also facing same issue after the initial rendering and tap on next button. All walkthroughable (View) re-render. Please check the video @pribeh when i'm tapping on Header things all icon looks like re-render. if i remove that walkthroughable view then everything working fine.

https://user-images.githubusercontent.com/105267464/182603412-4a60c6d2-c2b2-45fb-b0b5-bca3d5a4d862.mov

chrysb commented 3 months ago

Ran into the same issue. I've ripped apart this library to figure out what's going on.

In short, whenever data within the provider (and thus, useCopilot hook) changes, it triggers a re-render on all CopilotSteps. CopilotStep actually uses React.cloneElement underneath the hood, so it can't benefit from any sort of memoization.

return React.cloneElement(children, { copilot: copilotProps });

Since CopilotStep implements the useCopilot hook, it will trigger a re-render on all steps every time the current step changes in CopilotProvider, which should be unnecessary because once the measurement is complete, the provider should have all the information it needs to render the overlay.

Unfortunately, it's wasteful to wrap your entire app in something like this that will only be used once, but then remains in your tree for the rest of that user's lifetime, using CPU and re-rendering.

This is the peril of providers. I'll be looking into creating my own version of this using Zustand for global state instead, which will solve the re-render issue as the store and logic sits outside of the tree.