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

useMemo documentation #52

Closed
wants to merge 1 commit into from

Conversation

jamesdbrock
Copy link
Member

Is what I wrote true? If so then I think this is the best technique for preventing Hook components from re-rendering and we should explain that.

Is what I wrote true? If so then I think this is the best technique for preventing Hook components from re-rendering and we should explain that.
@megamaddu
Copy link
Member

Use this to prevent a Hook component from re-rendering needlessly by memoizing the props for the Hook component.

If a component is re-rendered with new props, it's going to re-render. useMemo won't stop that. You can use it to prevent other kinds of re-renders, though. For example, if you know a child component re-renders every time you pass it a new reference, even when the value is equal, you can use useMemo to preserve the initial, equivalent reference for passing down to the child.

React will skip re-rendering the component only if the new props is equal-by-reference to the old props
(or primitive and equal-by-value).

This is how React works in JavaScript, but it's not how this PureScript wrapper works. Notice the Eq deps constraint, which is used to determine whether the new dependency is not equal, causing a recompute the cached value. If you need JS reference equality (think ===), wrap your dependency in an UnsafeReference (this is what it's for).

@jamesdbrock
Copy link
Member Author

if you know a child component re-renders every time you pass it a new reference, even when the value is equal, you can use useMemo to preserve the initial, equivalent reference for passing down to the child.

I think this is what I was trying to say, but you put it better.

What do you mean by “if you know”? We know that it is always true that “a child component re-renders every time you pass it a new reference, even when the value is equal, you can use useMemo to preserve the initial, equivalent reference for passing down to the child.", right?

@jamesdbrock
Copy link
Member Author

Oh, maybe we don't know that. Because React probably assumes that our props object is mutable, so even when we pass the same-by-reference props object again, it might re-render?

Is there a way prevent a child component from re-rendering if the child component’s props are equal-by-value (but possibly not equal-by-reference) to the props from the last render?

@megamaddu
Copy link
Member

If the child component uses one of its props to control side effects. Ideally, if it's written in PS and you don't have tons of re-renders happening this should just work as expected. This is because both parent and child will be worrying about PS value equality (Eq). There may be some duplicate equality checks which can lead to performance issues in large apps, but that's what UnsafeReference + useMemo + memo (the one which uses React's shallow reference equality on props to avoid re-renders) solve. You probably don't want to reach for them unless you're experiencing a performance issue or you're building a library and feel enabling this kind of performance optimization is necessary.

React probably assumes that our props object is mutable

React props are immutable by convention, same as state.

Is there a way prevent a child component from re-rendering if the child component’s props are equal-by-value (but possibly not equal-by-reference) to the props from the last render?

memo enables this for a components props using shallow ref equality, and you can use useMemo to preserve those references in the parent using Eq/value equality. For a single parent/child pair this makes very little difference, but for large lists or app-level values which might cause entire app re-renders (or worse, re-mounts) this can sometimes be useful. Generally, though, you want a library to solve this for you.

@megamaddu
Copy link
Member

This is memo. It's a little awkward to use in PS since these are very JS/non-functional concepts, and it is side effecting for the same reason component creation is.. but sometimes it's what you need.

@megamaddu
Copy link
Member

If this library did have docs, this would all be in an "edge-case performance optimization" section 😅

@jamesdbrock
Copy link
Member Author

Okay thank you!

@megamaddu
Copy link
Member

You could also do this if using memo sounds sketch:

    child <- useMemo props \_ -> renderChild props
    pure child
    -- ^ only rebuilds children when props value equality changes

@jamesdbrock jamesdbrock deleted the patch-1 branch November 2, 2021 09:45
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.

None yet

2 participants