How to handle nested objects without re-render the whole app?
App example: user has columns, columns has todos, each todo has a done checkbox that can be toggled on and off, basic stuff
How should I manage the requests to this use-case? One request to fetch all data? or split the data fetch into individual requests for each column?
At some point, the entry data will have to be refetched/mutated/optimistic updated, and this will change the entry data reference and trigger a re-render to my whole app.
If I toggle one todo at column #85, all columns and all todos will be re-rendered.
Is there a way to subscribe a column/todo to his slice of that big nested entry data object only?
I'm rendering the columns like this
user.columns.map(column => <Column key column={column} />)
, so the column knows which slice of the big nested entry data object his data belongs, and must not be re-rendered if his slice didn't changed.
The solution I came up with is to use React.memo, deep comparing the column
prop to check if his slice have changed in these re-renders. This leads to only the <Column />
with the changed column props to be re-rendered.
Is it right? I feel like I'm missing something here.
I would like to put this single pieces of data together in one single root source, is easy to work this way.
A addNewColumn()
method must have a validation user.columns.getAmount() < user.plan.maxColumnsAllowed
. Creating these front-end business rules with all data in one source is a super easy.
Yes, I know re-render is not a bad thing but in my real use-case, I have a lot of "columns", each "column" have a lot of "todos", each "todo" has their own universe, their data, their modals, their dropdowns, their hooks... Re-render the whole list everytime a small change happened... If this is not a performance concern, I don't know what should be.
I put together this small POC.
https://github.com/vitormarkis/37react-query-best-practices-nested-objects
You can see in the GIFs, the behavior with and without React memo.GitHub
GitHub - vitormarkis/37react-query-best-practices-nested-objects: 3...
37react-query-best-practices-nested-objects. Contribute to vitormarkis/37react-query-best-practices-nested-objects development by creating an account on GitHub.


11 Replies
sunny-green•2y ago
React Query Render Optimizations
An advanced guide to minimize component re-renderings when using React Query
sunny-green•2y ago
The
select
property is your friendmute-goldOP•2y ago
It didn't work, it has the same result as the bad gif I send earlier. It seems like I can't have anything related to the user variable inside the Column component, otherwise it will add user as one of the component dependencies and re-render if the user value change
I see tk todo talking about partial subscriptions, but all his examples create the subscriptions of primitive values, like
todos => todos.length
, not nested objectseastern-cyan•2y ago
It can create subscriptions to nested objects too. It should work. If it doesn't, show a codesandbox please
mute-goldOP•2y ago
https://codesandbox.io/p/github/vitormarkis/37react-query-best-practices-nested-objects/main
toggle an todo and check the profiler, expect to re-render only the column/todo affected, got the whole app re-rendering
@TkDodo 🔮
eastern-cyan•2y ago
@vitor markis 🎈 well in
ColumnList
, you subscribe to the whole cache entry with:
and that triggers a top-down render of all Column
components. And since Column
isn't memoized, it will re-render. Since you only need the ids here, if you were to only select the ids, you wouldn't get a re-render because the ids didn't change.
here's a fixed version:
https://codesandbox.io/p/github/vitormarkis/37react-query-best-practices-nested-objects/csb-dwkrtx/draft/condescending-mccarthy
in case this doesn't work, here's the ColumnList component:
mute-goldOP•2y ago
It worked!
ColumnList now adds an array of ids as one of it's dependencies or adds each id string as it's dependencies to re-render?
eastern-cyan•2y ago
ColumnList is only subscribed to a list of ids, and that list never changes, so it doesn't re-render
mute-goldOP•2y ago
got you, but deleting or adding new column is causing the whole list to re-render since this array of IDs is changing
eastern-cyan•2y ago
sure, it has to. a column could've been added in the middle
mute-goldOP•2y ago
nice, thank you