I'm having an issue with identifying bottlenecks in render performance while working on a JSON viewer. With few elements, it performs well, but at a certain point it becomes annoyingly slow.
Checking the profiler, it seems that elements are rendering fast enough, but I've noticed a few issues that I'm not sure how to pursue.
Overview
- The app is a JSON viewer which allows you to expand / minimize all elements at once, as well as individual elements.
- Performance is fine with few elements, but seems to decrease dramatically as the number of elements increases.
- When profiling both my object filter method with
performance.now()
as well as checking the render time in React DevTools, the figures seem okay. I could be interpreting it wrong. - I've tried using
React.memo()
on stateless elements (particularly the key/value which is the most frequently rendered component), but it doesn't seem to improve the performance noticeably. Admittedly, I'm not sure if I understand the reasoning enough behind memoizing React components to implement this usefully.
Implementation
- Currently, my app loads data into a parent which feeds into a component that loads the JSON tree using a recursive element.
- Loading JSON feed from URL changes the state of the parent component, which is filtered using a helper method that uses values entered into an input field.
Issues
There are two functionalities which reproduce a slow response time with (not so big) JSON documents:
- The expand all button
- The first few keypresses on a filter query
With the current implementation, both filtering and expanding all triggers a display: none
change on the child elements, and the behavior leads me to believe I'm doing something inefficiently to handle this use case.
Reproduction Steps
The code is available here: https://codesandbox.io/s/react-json-view-4z348
With a production build here (not performing any better): https://csb-4z348.vercel.app/
To reproduce the issue, play around with the Expand All function (plus sign next to filter input) and some filter inputs.
Then, try loading a JSON feed with more elements (you can test on my GitHub API feed) and try filtering/expanding all. Notice the major performance hit.
What I've noticed
- When logging useEffect, minimizing seems to cause ~2x as many rerenders as expanding all.
- As the filter input becomes more specific, the performance (logically) improves as less elements are being rendered.
Question
While I would appreciate a nudge in the right direction for this specific case, what I'm most curious about is how best to identify what is causing these performance issues.
I've looked into windowing the output, but it's not my first choice, and I'm pretty sure I'm doing something wrong, rather than the cause being too many elements rendered.
I appreciate your time, and thank you in advance for any tips you could provide!