Skip to content

Instantly share code, notes, and snippets.

@nluo
Created February 3, 2020 03:10
Show Gist options
  • Save nluo/71b2beb595f6960fadc238e0069c7ee8 to your computer and use it in GitHub Desktop.
Save nluo/71b2beb595f6960fadc238e0069c7ee8 to your computer and use it in GitHub Desktop.
React memo examples
This is working as designed. There is a longer discussion about this in #14110 if you're curious.
Let's say for some reason you have AppContext whose value has a theme property, and you want to only re-render some ExpensiveTree on appContextValue.theme changes.
TLDR is that for now, you have three options:
Option 1 (Preferred): Split contexts that don't change together
If we just need appContextValue.theme in many components but appContextValue itself changes too often, we could split ThemeContext from AppContext.
function Button() {
let theme = useContext(ThemeContext);
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}
Now any change of AppContext won't re-render ThemeContext consumers.
This is the preferred fix. Then you don't need any special bailout.
Option 2: Split your component in two, put memo in between
If for some reason you can't split out contexts, you can still optimize rendering by splitting a component in two, and passing more specific props to the inner one. You'd still render the outer one, but it should be cheap since it doesn't do anything.
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return <ThemedButton theme={theme} />
}
const ThemedButton = memo(({ theme }) => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
});
Option 3: One component with useMemo inside
Finally, we could make our code a bit more verbose but keep it in a single component by wrapping return value in useMemo and specifying its dependencies. Our component would still re-execute, but React wouldn't re-render the child tree if all useMemo inputs are the same.
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return useMemo(() => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}, [theme])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment