Skip to content

Commit c9bc0b5

Browse files
carburodhavall08gaearonmadany01kunxl-gg
authored
Merge pull request #606 from reactjs/sync-e50e5634
* [Beta] Update text with cloneElement (#5268) * Clarify example * Add note about getSnapshotBeforeUpdate * [Beta] createRef API (#5270) * [Beta] PureComponent API (#5271) * [Beta] useDebugValue API (#5272) * Fix title * Fix typo * [Beta] Fix Defining frameId in useAnimationLoop (#5277) * Added undefined to in the list of possible return types of render function (#5275) Co-authored-by: Shanmughapriyan S <[email protected]> Co-authored-by: Sebastian Silbermann <[email protected]> * Resolve merge conflicts Co-authored-by: Dhaval Laiya <[email protected]> Co-authored-by: Dan Abramov <[email protected]> Co-authored-by: Ahmad Madany <[email protected]> Co-authored-by: Kunal Tiwari <[email protected]> Co-authored-by: Shanmughapriyan S <[email protected]> Co-authored-by: Sebastian Silbermann <[email protected]> Co-authored-by: Rainer Martínez Fraga <[email protected]>
2 parents 1c75d35 + 8e1b434 commit c9bc0b5

10 files changed

+497
-38
lines changed
Loading

beta/src/content/apis/react/Component.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,18 +278,28 @@ We recommend to define components as functions instead of classes. [See how to m
278278

279279
Typically, you will [define components as functions](/learn/your-first-component#defining-a-component) instead.
280280

281-
For example, suppose you're converting this class to a function:
281+
For example, suppose you're converting this `Greeting` class component to a function:
282282

283283
<Sandpack>
284284

285285
```js
286286
import { Component } from 'react';
287287

288-
export default class Greeting extends Component {
288+
class Greeting extends Component {
289289
render() {
290290
return <h1>Hello, {this.props.name}!</h1>;
291291
}
292292
}
293+
294+
export default function App() {
295+
return (
296+
<>
297+
<Greeting name="Sara" />
298+
<Greeting name="Cahal" />
299+
<Greeting name="Edite" />
300+
</>
301+
);
302+
}
293303
```
294304

295305
</Sandpack>
@@ -336,7 +346,7 @@ export default function App() {
336346

337347
### Migrating a component with state from a class to a function {/*migrating-a-component-with-state-from-a-class-to-a-function*/}
338348

339-
Suppose you're converting this class to a function:
349+
Suppose you're converting this `Counter` class component to a function:
340350

341351
<Sandpack>
342352

@@ -458,7 +468,7 @@ button { display: block; margin-top: 10px; }
458468
459469
### Migrating a component with lifecycle methods from a class to a function {/*migrating-a-component-with-lifecycle-methods-from-a-class-to-a-function*/}
460470
461-
Suppose you're converting this component with lifecycle methods to a function:
471+
Suppose you're converting this `ChatRoom` class component with lifecycle methods to a function:
462472
463473
<Sandpack>
464474
@@ -1436,6 +1446,12 @@ You should return a snapshot value of any type that you'd like, or `null`. The v
14361446
14371447
- `getSnapshotBeforeUpdate` will not get called if [`shouldComponentUpdate`](#shouldcomponentupdate) is defined and returns `false`.
14381448
1449+
<Note>
1450+
1451+
At the moment, there is no equivalent to `getSnapshotBeforeUpdate` for function components. This use case is very uncommon, but if you have the need for it, for now you'll have to write a class component.
1452+
1453+
</Note>
1454+
14391455
---
14401456
14411457
### `render()` {/*render*/}
Lines changed: 192 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,210 @@
11
---
2-
title: React.PureComponent
2+
title: PureComponent
33
---
44

5-
<Wip>
5+
<Pitfall>
66

7-
This section is incomplete, please see the old docs for [React.PureComponent.](https://reactjs.org/docs/react-api.html#reactpurecomponent)
8-
9-
</Wip>
7+
We recommend to define components as functions instead of classes. [See how to migrate.](#alternatives)
108

9+
</Pitfall>
1110

1211
<Intro>
1312

14-
React.PureComponent is similar to React.Component. The difference between them is that React.Component doesn’t implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison.
15-
16-
If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.
13+
`PureComponent` is similar to [`Component`](/apis/react/Component) but it skips re-renders for same props and state. Class components are still supported by React, but we don't recommend using them in new code.
1714

1815
```js
19-
class Welcome extends React.PureComponent {
16+
class Greeting extends PureComponent {
2017
render() {
21-
return <h1>Hello, {this.props.name}</h1>;
18+
return <h1>Hello, {this.props.name}!</h1>;
2219
}
2320
}
2421
```
2522

2623
</Intro>
2724

2825
<InlineToc />
26+
27+
---
28+
29+
## Usage {/*usage*/}
30+
31+
### Skipping unnecessary re-renders for class components {/*skipping-unnecessary-re-renders-for-class-components*/}
32+
33+
React normally re-renders a component whenever its parent re-renders. As an optimization, you can create a component that React will not re-render when its parent re-renders so long as its new props and state are the same as the old props and state. [Class components](/apis/react/Component) can opt into this behavior by extending `PureComponent`:
34+
35+
```js {1}
36+
class Greeting extends PureComponent {
37+
render() {
38+
return <h1>Hello, {this.props.name}!</h1>;
39+
}
40+
}
41+
```
42+
43+
A React component should always have [pure rendering logic.](/learn/keeping-components-pure) This means that it must return the same output if its props, state, and context haven't changed. By using `PureComponent`, you are telling React that your component complies with this requirement, so React doesn't need to re-render as long as its props and state haven't changed. However, your component will still re-render if a context that it's using changes.
44+
45+
In this example, notice that the `Greeting` component re-renders whenever `name` is changed (because that's one of its props), but not when `address` is changed (because it's not passed to `Greeting` as a prop):
46+
47+
<Sandpack>
48+
49+
```js
50+
import { PureComponent, useState } from 'react';
51+
52+
class Greeting extends PureComponent {
53+
render() {
54+
console.log("Greeting was rendered at", new Date().toLocaleTimeString());
55+
return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>;
56+
}
57+
}
58+
59+
export default function MyApp() {
60+
const [name, setName] = useState('');
61+
const [address, setAddress] = useState('');
62+
return (
63+
<>
64+
<label>
65+
Name{': '}
66+
<input value={name} onChange={e => setName(e.target.value)} />
67+
</label>
68+
<label>
69+
Address{': '}
70+
<input value={address} onChange={e => setAddress(e.target.value)} />
71+
</label>
72+
<Greeting name={name} />
73+
</>
74+
);
75+
}
76+
```
77+
78+
```css
79+
label {
80+
display: block;
81+
margin-bottom: 16px;
82+
}
83+
```
84+
85+
</Sandpack>
86+
87+
<Pitfall>
88+
89+
We recommend to define components as functions instead of classes. [See how to migrate.](#alternatives)
90+
91+
</Pitfall>
92+
93+
---
94+
95+
## Alternatives {/*alternatives*/}
96+
97+
### Migrating from a `PureComponent` class component to a function {/*migrating-from-a-purecomponent-class-component-to-a-function*/}
98+
99+
We recommend to use function components instead of [class components](/apis/react/Component) in the new code. If you have some existing class components using `PureComponent`, here is how you can convert them. This is the original code:
100+
101+
<Sandpack>
102+
103+
```js
104+
import { PureComponent, useState } from 'react';
105+
106+
class Greeting extends PureComponent {
107+
render() {
108+
console.log("Greeting was rendered at", new Date().toLocaleTimeString());
109+
return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>;
110+
}
111+
}
112+
113+
export default function MyApp() {
114+
const [name, setName] = useState('');
115+
const [address, setAddress] = useState('');
116+
return (
117+
<>
118+
<label>
119+
Name{': '}
120+
<input value={name} onChange={e => setName(e.target.value)} />
121+
</label>
122+
<label>
123+
Address{': '}
124+
<input value={address} onChange={e => setAddress(e.target.value)} />
125+
</label>
126+
<Greeting name={name} />
127+
</>
128+
);
129+
}
130+
```
131+
132+
```css
133+
label {
134+
display: block;
135+
margin-bottom: 16px;
136+
}
137+
```
138+
139+
</Sandpack>
140+
141+
When you [convert this component from a class to a function,](/apis/react/Component#alternatives) wrap it in [`memo`:](/apis/react/memo)
142+
143+
<Sandpack>
144+
145+
```js
146+
import { memo, useState } from 'react';
147+
148+
const Greeting = memo(function Greeting({ name }) {
149+
console.log("Greeting was rendered at", new Date().toLocaleTimeString());
150+
return <h3>Hello{name && ', '}{name}!</h3>;
151+
});
152+
153+
export default function MyApp() {
154+
const [name, setName] = useState('');
155+
const [address, setAddress] = useState('');
156+
return (
157+
<>
158+
<label>
159+
Name{': '}
160+
<input value={name} onChange={e => setName(e.target.value)} />
161+
</label>
162+
<label>
163+
Address{': '}
164+
<input value={address} onChange={e => setAddress(e.target.value)} />
165+
</label>
166+
<Greeting name={name} />
167+
</>
168+
);
169+
}
170+
```
171+
172+
```css
173+
label {
174+
display: block;
175+
margin-bottom: 16px;
176+
}
177+
```
178+
179+
</Sandpack>
180+
181+
<Note>
182+
183+
Unlike `PureComponent`, [`memo`](/apis/react/memo) does not compare the new and the old state. In function components, calling the [`set` function](/apis/react/useState#setstate) with the same state [already prevents re-renders by default,](/apis/react/memo#updating-a-memoized-component-using-state) even without `memo`.
184+
185+
</Note>
186+
187+
---
188+
189+
## Reference {/*reference*/}
190+
191+
### `PureComponent` {/*purecomponent*/}
192+
193+
To skip re-rendering a class component for same props and state, extend `PureComponent` instead of [`Component`:](/apis/react/Component)
194+
195+
```js
196+
import { PureComponent } from 'react';
197+
198+
class Greeting extends PureComponent {
199+
render() {
200+
return <h1>Hello, {this.props.name}!</h1>;
201+
}
202+
}
203+
```
204+
205+
`PureComponent` is a subclass of `Component` and supports [all the `Component` APIs.](/apis/react/Component#reference) Extending `PureComponent` is equivalent to defining a custom [`shouldComponentUpdate`](/apis/react/Component#shouldcomponentupdate) method that shallowly compares props and state.
206+
207+
208+
[See more examples.](#usage)
209+
210+

beta/src/content/apis/react/cloneElement.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,6 @@ Usually, you'll return the element from your component or make it a child of ano
689689
690690
* Cloning an element **does not modify the original element.**
691691
692-
* You should only **pass children as multiple arguments to `createElement` if they are all statically known,** like `cloneElement(element, null, child1, child2, child3)`. If your children are dynamic, pass the entire array as the third argument: `cloneElement(element, null, listItems)`. This ensures that React will [warn you about missing `key`s](/learn/rendering-lists#keeping-list-items-in-order-with-key) for any dynamic lists. For static lists this is not necessary because they never reorder.
692+
* You should only **pass children as multiple arguments to `cloneElement` if they are all statically known,** like `cloneElement(element, null, child1, child2, child3)`. If your children are dynamic, pass the entire array as the third argument: `cloneElement(element, null, listItems)`. This ensures that React will [warn you about missing `key`s](/learn/rendering-lists#keeping-list-items-in-order-with-key) for any dynamic lists. For static lists this is not necessary because they never reorder.
693693
694694
* `cloneElement` makes it harder to trace the data flow, so **try the [alternatives](/#alternatives) instead.**

0 commit comments

Comments
 (0)