Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf[react-native]: Memoized Blocks Component to free up UI thread. #3814

Merged
merged 7 commits into from
Jan 24, 2025

Conversation

yash-builder
Copy link
Contributor

@yash-builder yash-builder commented Jan 13, 2025

Description

Suspense:
Added React.Suspense to defer the rendering of the Content component until it is fully loaded.

Memoization:
React.memo to memoize computationally expensive operations within the Blocks component. To prevents unnecessary recalculations of processed blocks during re-renders, reducing the load on the UI thread.

Screenshot
Before:
Screenshot 2025-01-13 at 12 20 38 PM

After:
Screenshot 2025-01-13 at 12 37 41 PM

Copy link

changeset-bot bot commented Jan 13, 2025

🦋 Changeset detected

Latest commit: 5533720

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@builder.io/sdk-react-native Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

nx-cloud bot commented Jan 13, 2025

View your CI Pipeline Execution ↗ for commit 5533720.

Command Status Duration Result
nx test @e2e/nextjs-sdk-next-app ✅ Succeeded 7m 45s View ↗
nx test @e2e/qwik-city ✅ Succeeded 7m 22s View ↗
nx test @e2e/nuxt ✅ Succeeded 6m 59s View ↗
nx test @e2e/react-sdk-next-15-app ✅ Succeeded 5m 45s View ↗
nx test @e2e/hydrogen ✅ Succeeded 5m 40s View ↗
nx test @e2e/react-sdk-next-14-app ✅ Succeeded 5m 6s View ↗
nx test @e2e/react-native ✅ Succeeded 5m 21s View ↗
nx test @e2e/vue ✅ Succeeded 4m 55s View ↗
Additional runs (34) ✅ Succeeded ... View ↗

☁️ Nx Cloud last updated this comment at 2025-01-24 04:06:12 UTC

Copy link
Contributor

@midhunadarvin midhunadarvin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work @yash-builder

));

// Optional: Give the component a display name for better debugging
RenderBlock.displayName = 'RenderBlock';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 suggestion:
Should we append block.id to the displayName as a identifier ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can surely do that. But in this scenario I used this identifier for inspecting the component in React Devtools

};

// Moved outside and memoized
const RenderBlock = memo(({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question:
We have used memo over Block component ( to get RenderBlock ) and then composed the RenderBlock with React.useCallback. Could you explain the logic here and how it works internally ?

  • what happens if we use memo / useCallback in both places ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question!

  • If Only memo Is Used:
    RenderBlock will avoid re-renders, but FlatList may still recreate the renderItem function on every render. This may lead to potential performance bottleneck.
  • If Only useCallback Is Used:
    The renderItem function will be stable, but RenderBlock will re-render if its props are shallowly different, even when not required.

examples/nextjs-app-dir-v2/package.json Show resolved Hide resolved
Copy link
Contributor

@samijaber samijaber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very well done! I'm Rewriting here what I sent you in Slack so we don't lose track of it.

One important thing is not to use overrides/* unless as a last resort because the file will quickly go out of sync with the original Blocks.lite.tsx, forcing us to maintain multiple copies of the same logic.

Here is a Loom showing how I'd tackle the ~3-4 changes in your PR and incorporate them into Mitosis plugins instead:

https://www.loom.com/share/94f1767796bd487bb48be41d9046e01f

Also, you need to add a changesets entry, which you can do by following https://github.com/BuilderIO/builder/blob/main/packages/sdks/PUBLISHING.md

Copy link
Contributor

@samijaber samijaber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good! You're still missing the changesets entry https://github.com/BuilderIO/builder/blob/main/packages/sdks/PUBLISHING.md#1--add-changeset

Copy link
Contributor

@samijaber samijaber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@samijaber samijaber merged commit 12b35b2 into BuilderIO:main Jan 24, 2025
50 checks passed
@yash-builder yash-builder deleted the perf-react-native branch January 27, 2025 01:31
@yash-builder yash-builder self-assigned this Jan 27, 2025
@yash-builder yash-builder added the bug Something isn't working label Jan 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants