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

simplify syncing props to state in ThemeProvider #4855

Merged
merged 2 commits into from
Aug 16, 2024

Conversation

mattcosta7
Copy link
Collaborator

@mattcosta7 mattcosta7 commented Aug 16, 2024

Closes #

Changelog

New

Added a useSyncedState hook that avoids using useEffect to sync state when props change inline.

I think it's likely this could be applied to other components in primer to save a render occasionally, but can easily be used elsewhere once it's in the codebase

Changed

In ThemeProvider I used the useSyncedState hook which was added in this PR.

This hook tracks the values used to initialize the state and syncs in the initial render pass instead of in a useEffect, which should avoid a handful of theme provider renders in some cases. it also avoids the need to use a useEffect to sync the state when the props change inline - making the code a bit clearer. These are no longer synced after render but mid-render leading to a few render passes being skipped

Removed

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

Merge checklist

@mattcosta7 mattcosta7 self-assigned this Aug 16, 2024
Copy link

changeset-bot bot commented Aug 16, 2024

🦋 Changeset detected

Latest commit: 6c5af04

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

This PR includes changesets to release 1 package
Name Type
@primer/react 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
Contributor

github-actions bot commented Aug 16, 2024

size-limit report 📦

Path Size
packages/react/dist/browser.esm.js 96.3 KB (+0.03% 🔺)
packages/react/dist/browser.umd.js 96.59 KB (+0.04% 🔺)

Comment on lines -107 to -119
// Update state if props change
React.useEffect(() => {
setColorMode(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
}, [props.colorMode, fallbackColorMode])

React.useEffect(() => {
setDayScheme(props.dayScheme ?? fallbackDayScheme ?? defaultDayScheme)
}, [props.dayScheme, fallbackDayScheme])

React.useEffect(() => {
setNightScheme(props.nightScheme ?? fallbackNightScheme ?? defaultNightScheme)
}, [props.nightScheme, fallbackNightScheme])

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

these are all synced automatically in the useSyncedState calls and avoid useEffect so we get to skip a render pass every time one changes

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

also, I doubt these get hit often, but I saw this while looking at something related and just figured why not

@mattcosta7 mattcosta7 changed the title simplify syncing updates for theme provider simplify syncing props to state in ThemeProvider Aug 16, 2024
@mattcosta7 mattcosta7 marked this pull request as ready for review August 16, 2024 15:47
@mattcosta7 mattcosta7 requested a review from a team as a code owner August 16, 2024 15:47
@mattcosta7 mattcosta7 requested a review from langermank August 16, 2024 15:47
@langermank langermank removed their request for review August 16, 2024 15:48
Comment on lines +21 to +25
const nextInitialValue = initialValue instanceof Function ? initialValue() : initialValue
if (!isPropUpdateDisabled && !isEqual(previous, nextInitialValue)) {
setPrevious(nextInitialValue)
setState(nextInitialValue)
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

these setState calls in render are all good because they're done in the same component. This will immediately queue an update and re-render instead of completing a render, then comparing in a useEffect, queuing an update and then rendering again then re-comparing.

the main value is we save a full render from react on any change - a render we know will immediately be discarded

Copy link
Member

@joshblack joshblack left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for doing this 🥳

@primer-integration
Copy link

👋 Hi from github/github! Your integration PR is ready: https://github.com/github/github/pull/337959

@mattcosta7 mattcosta7 added this pull request to the merge queue Aug 16, 2024
Merged via the queue into main with commit 873249a Aug 16, 2024
37 checks passed
@mattcosta7 mattcosta7 deleted the simplify-theme-provider-syncing-updates branch August 16, 2024 21:07
@primer primer bot mentioned this pull request Aug 16, 2024
@primer primer bot mentioned this pull request Oct 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants