-
-
Notifications
You must be signed in to change notification settings - Fork 251
Add page about React.memo #889
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
"events", | ||
"refs-and-the-dom", | ||
"context", | ||
"memo", | ||
"styling", | ||
"router", | ||
"lazy-components", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
--- | ||
title: memo | ||
description: "using React.memo" | ||
canonical: "/docs/react/latest/memo" | ||
--- | ||
|
||
# memo | ||
|
||
`React.memo` lets you skip re-rendering a component when its props are unchanged. | ||
|
||
Wrap a component in memo to get a memoized version of that component. | ||
This memoized version of your component will usually not be re-rendered when its parent component is re-rendered as long as its props have not changed. | ||
|
||
<small>But React may still re-render it: memoization is a performance optimization, not a guarantee.</small> | ||
|
||
<CodeTab labels={["ReScript", "JS Output"]}> | ||
|
||
```res | ||
@react.component | ||
let make = React.memo((~a: int, ~b: string) => { | ||
<div> | ||
{React.int(a)} | ||
<br /> | ||
{React.string(b)} | ||
</div> | ||
}) | ||
``` | ||
|
||
```js | ||
import * as React from "react"; | ||
import * as JsxRuntime from "react/jsx-runtime"; | ||
|
||
var make = React.memo(function (props) { | ||
return JsxRuntime.jsxs("div", { | ||
children: [ | ||
props.a, | ||
JsxRuntime.jsx("br", {}), | ||
props.b | ||
] | ||
}); | ||
}); | ||
``` | ||
|
||
</CodeTab> | ||
|
||
## arePropsEqual | ||
|
||
In React, memo can accept an optional argument called "arePropsEqual". This function takes two arguments: the previous props and the new props of the component. | ||
It should return true if the old and new props are the same, meaning the component will produce the same output and behavior with the new props as it did with the old ones. | ||
|
||
In ReScript, to use the `arePropsEqual` function, you must redefine the `make` binding with `React.memoCustomCompareProps`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about "must" here, because, as you demonstrated, there are other ways as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a bit of "must" in the sense that you cannot just write: So, you must do something other than that to get it to work. Which is the exact thing I want to add to the documentation, as that was confusing to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other thing you can do is to not use the JSX preprocessor extension at all btw (i.e. no type props = {
disabled: bool,
onClick: JsxEvent.Mouse.t => unit,
}
let make = React.memoCustomCompareProps(
({disabled, onClick}) => {
<button
disabled={disabled}
onClick={ev => ev->JsxEvent.Mouse.preventDefault->onClick}>
{React.string("My button")}
</button>
},
(p1, p2) => p1.disabled == p2.disabled,
) so maybe we can keep the "must", but give an alternative solution There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I rephrased it to emphasize you can't combine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For my own understanding, does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since JSX4, what the annotation does is basically generating a props type (probably with more generic types though). So no, using them is identical. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, thank you! |
||
|
||
<CodeTab> | ||
|
||
```res | ||
@react.component | ||
let make = (~disabled, ~onClick) => { | ||
<button | ||
disabled={disabled} | ||
onClick={ev => ev->JsxEvent.Mouse.preventDefault->onClick}> | ||
{React.string("My button")} | ||
</button> | ||
} | ||
|
||
let make = React.memoCustomCompareProps(make, (p1, p2) => | ||
p1.disabled == p2.disabled | ||
) | ||
``` | ||
|
||
```js | ||
import * as React from "react"; | ||
import * as JsxRuntime from "react/jsx-runtime"; | ||
|
||
function Playground(props) { | ||
var onClick = props.onClick; | ||
return JsxRuntime.jsx("button", { | ||
children: "My button", | ||
disabled: props.disabled, | ||
onClick: (function (ev) { | ||
onClick((ev.preventDefault(), undefined)); | ||
}) | ||
}); | ||
} | ||
|
||
var make = React.memo(Playground, (function (p1, p2) { | ||
return p1.disabled === p2.disabled; | ||
})); | ||
``` | ||
|
||
</CodeTab> |
Uh oh!
There was an error while loading. Please reload this page.