Skip to content

Commit 7ac0712

Browse files
committed
Updated 16.3 blog post to account for getSnapshotBeforeUpdate lifecycle
1 parent c41bb29 commit 7ac0712

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

content/blog/2018-03-20-react-v-16-3.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "React v16.3.0: New lifecycles and context API"
33
author: [bvaughn]
44
---
55

6-
This release includes a new class component lifecycle (`getDerivedStateFromProps`), a new `StrictMode` component, an official context API, a new ergonomic ref API, and a ref-forwarding API!
6+
This release includes an official context API, new class component lifecycles, a new `StrictMode` component, a new ergonomic ref API, and a ref-forwarding API!
77

88
For the past few months, the React team has been working on support for [asynchronous rendering](/blog/2018/03/01/sneak-peek-beyond-react-16.html). We are excited about the new features it will enable.
99

@@ -64,15 +64,17 @@ For example, with the current API, it is too easy to block the initial render wi
6464

6565
Many of these issues are exacerbated by a subset of the component lifecycles (`componentWillMount`, `componentWillReceiveProps`, and `componentWillUpdate`). These also happen to be the lifecycles that cause the most confusion within the React community. For these reasons, we are going to deprecate those methods in favor of better alternatives.
6666

67-
We recognize that this change will impact many existing components. (At Facebook, we maintain more than 50,000 React components, and we can't tell our engineers to rewrite them either.) Because of this, the migration path will be as gradual as possible, and will provide escape hatches.
67+
We recognize that this change will impact many existing components. Because of this, the migration path will be as gradual as possible, and will provide escape hatches. (At Facebook, we maintain more than 50,000 React components. We depend on a gradual release cycle too!)
6868

6969
> **Note:**
7070
>
7171
> Deprecation warnings will be enabled with a future 16.x release, **but the legacy lifecycles will continue to work until version 17**.
7272
>
7373
> Even in version 17, it will still be possible to use them, but they will be aliased with an "UNSAFE_" prefix to indicate that they might cause issues. We have also prepared an [automated script to rename them](https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles) in existing code.
7474

75-
We are also adding a new static lifecycle, `getDerivedStateFromProps`, as a safer alternative to the legacy `componentWillReceiveProps`.
75+
In addition to deprecating unsafe lifecycles, we are also adding a couple of new lifecyles:
76+
* [`getDerivedStateFromProps`](/docs/react-component.html#static-getderivedstatefromprops) is being added as a safer alternative to the legacy `componentWillReceiveProps`.
77+
* [`getSnapshotBeforeUpdate`](/docs/react-component.html#getsnapshotbeforeupdate) is being added to support safely reading properties from e.g. the DOM before updates are made.
7678

7779
[Learn more about these lifecycle changes here.](#TODO-link-to-update-on-async-blog-post)
7880

content/docs/reference-react-component.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,13 @@ If you need to update `state` in response to `props` changes, use `UNSAFE_compon
295295

296296
### `getSnapshotBeforeUpdate()`
297297

298-
`getSnapshotBeforeUpdate()` is invoked right before the most recently rendered output is committed to e.g. the DOM. It enables your component to capture current values (e.g. scroll position) before they are potential changed.
298+
`getSnapshotBeforeUpdate()` is invoked right before the most recently rendered output is committed to e.g. the DOM. It enables your component to capture current values (e.g. scroll position) before they are potential changed. Any value returned by this lifecycle will be passed as a parameter to `componentDidUpdate()`.
299299

300-
Any value returned by this lifecycle will be passed as a parameter to `componentDidUpdate()`.
300+
For example:
301+
302+
`embed:react-component-reference/get-snapshot-before-update.js`
303+
304+
In the above examples, it is important to read the `scrollHeight` property in `getSnapshotBeforeUpdate` rather than `componentWillUpdate` in order to support async rendering. With async rendering, there may be delays between "render" phase lifecycles (like `componentWillUpdate` and `render`) and "commit" phase lifecycles (like `getSnapshotBeforeUpdate` and `componentDidUpdate`). If a user does something like resize the browser during this time, a `scrollHeight` value read from `componentWillUpdate` will be stale.
301305

302306
* * *
303307

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class ScrollingList extends React.Component {
2+
listRef = React.createRef();
3+
4+
getSnapshotBeforeUpdate(prevProps, prevState) {
5+
// Are we adding new items to the list?
6+
// Capture the current height of the list so we can adjust scroll later.
7+
if (prevProps.list.length < this.props.list.length) {
8+
return this.listRef.current.scrollHeight;
9+
}
10+
return null;
11+
}
12+
13+
componentDidUpdate(prevProps, prevState, snapshot) {
14+
// If we have a snapshot value, we've just added new items.
15+
// Adjust scroll so these new items don't push the old ones out of view.
16+
if (snapshot !== null) {
17+
this.listRef.current.scrollTop +=
18+
this.listRef.current.scrollHeight - snapshot;
19+
}
20+
}
21+
22+
render() {
23+
return (
24+
<div ref={this.listRef}>{/* ...contents... */}</div>
25+
);
26+
}
27+
}

0 commit comments

Comments
 (0)