Improve frontend performance by avoiding useless renders #1321
+64
−36
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The original goal was to speed up the search page (since it was rendered multiple times, uselessly), but these changes benefit all of Tobira. This generally cuts down on duplicate renders and useless work that is done. You can see this effect by adding
console.log
statements toActiveRoute
, a route of your choice likeRealmPage
and some other places. Do make sure to remove<StrictMode>
for testing, as that doubles all renders again, making it harder to see. It's also helpful to addtokio::time::sleep(std::time::Duration::from_millis(1500)).await;
tohandle_api
to easily see loading states.This is a bit infuriating as it's still not perfect. But I cannot find a way to fix the last bit and searching for in-depth information on this stuff is super hard. I only find surface-level resources on this. Even blog posts which title contains "in-depth" or "deep dive" are laughably shallow. The react docs are good in principle but leave out some behind the scene information that would aid with debugging. The React dev tools are also surprisingly unhelpful.
Here is some information on what is rendered when:
Initial load
That's actually perfect as far as I can tell. First the request is sent, then the router routes and tries to render the active route, which leads to
<RootLoader>
suspending (then showing <InitialLoading />
). Once the response arrives, the child of<Suspense>
(<ActiveRoute>
) is rerendered, and this timeRootLoader
does not suspend, so the RealmPage is rendered (only once!).Clicking on a link
Good: the GQL request is sent first thing. Then the router is rerendered because
isPending
switches totrue
, which causes the loading indicator to do its thing. But:Before the response arrives, we already have one duplicate rendering. Why is the router rendered twice with exact same props and all? This goes down to the
RootLoader
twice, which suspends both times I suspect. I actually know how to make it go away: Removing<LoadingIndicator>
completely gets rid of one duplication (the last four lines before network arrives). But all the ways I tried to add loading indicator back again resulted in a duplicate render again. But oh well, at least the actual<RealmPage>
is not rendered, so it should all be fairly cheap.Secondly, after the response arrives, the
RootLoader
is rendered for an unknown reason. If it weren't for the last commit, that would rerender theRealmPage
with the previous data! No idea why. And then everything is freshly rendered starting withRouter
down toRealmPage
.So... as far as I can see, the actual page (
RealmPage
in this case) is not rendered uselessly. Which is already a success. But still, weird stuff is happening and as I said, it's infuriating.