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

RFC: Memoize functional components by default #108

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions text/0069-memo-by-default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
- Start Date: 2019-02-25
- RFC PR: (leave this empty)
- React Issue: (leave this empty)

# Summary

- Make functional components implement `React.memo` by default
- Add `React.always` that flags the functional component to be treated as it is currently
- Add a warning to `React.memo` when it is used without defining `arePropsEqual`.

# Basic example

```js
import { always } from 'react';

function Button(props) {
// Component code
}

// for users who wish to opt out of memoization
export default always(Button);
```

Only import `memo` if `arePropsEqual` is implemented.

```js
function arePropsEqual(prevProps, nextProps) {
return prevProps.color.id === nextProps.color.id;
}

// warning is given is arePropsEqual is undefined
export default memo(Button, arePropsEqual);
```

# Motivation

With hooks becoming more widely accepted, there will be many cases where the component tree could be made up of entirely functional components.

In such cases, `React.memo` is needed to prevent children from rerendering.

However, it can become easy to forget to memoize a functional component.

In most cases, I believe reconciliation to be a more expensive operation than diffing props.

# Detailed design

`React.always` returns a component type that tells React "render the inner type and do not bail out".

`React.always` accepts any valid component type as the first argument. This ensures that it can safely wrap an import without being concerned about its implementation details.

# Drawbacks

- Breaking change and potentially slow.

# Alternatives

- Call it something different like `unmemo`.

# Adoption strategy

This is a breaking change, therefore any functional componenets that rely on the render never bailing out will need to implement `React.always`. Components that implement `React.memo` will not have their implementation changed, however if `arePropsEqual` is not implemented, a warning will be given in developer mode.

# How we teach this

Many other UI libraries/frameworks advertise this sort of optimization as being selling point. I believe for most users this is expected to be done already.

# Unresolved questions

- Will memoization by default be slower on average than reconciliation?