Browse Source

Added React.forwardRef to 16.3 release blog post

main
Brian Vaughn 7 years ago
parent
commit
a357b64503
  1. 19
      content/blog/2018-03-20-react-v-16-3.md
  2. 2
      examples/16-3-release-blog-post/create-ref-example.js
  3. 32
      examples/16-3-release-blog-post/fancy-button-example.js
  4. 34
      examples/16-3-release-blog-post/forward-ref-example.js
  5. 10
      examples/16-3-release-blog-post/hoc-theme-example.js

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

@ -1,9 +1,9 @@
---
title: "React v16.3.0: New lifecycles and context"
title: "React v16.3.0: New lifecycles and context API"
author: [bvaughn]
---
This release includes a new class component lifecycle (`getDerivedStateFromProps`), a new `StrictMode` component, an official context API, and a new ergonomic ref API!
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!
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.
@ -41,6 +41,21 @@ Version 16.3 adds a new option for managing refs that offers the convenience of
[Learn more about the new `createRef` API here.](/docs/refs-and-the-dom.html)
## `forwardRef` API
[Higher-order components](/docs/higher-order-components.html) (or HOCs) are a common way to reuse code between components. Building on the theme context example from above, we might create an HOC that injects the current "theme" as a prop:
`embed:16-3-release-blog-post/hoc-theme-example.js`
We can use the above HOC to wire components up to the theme context without having to use `ThemeContext` directly. For example:
`embed:16-3-release-blog-post/fancy-button-example.js`
HOCs typically [pass props through](/docs/higher-order-components.html#convention-pass-unrelated-props-through-to-the-wrapped-component) to the components they wrap. Unfortunately, [refs are not passed through](/docs/higher-order-components.html#refs-arent-passed-through). This means that we can't attach a ref to `FancyButton` if we use `FancyThemedButton`- so there's no way for us to call `focus()`.
The new `forwardRef` API solves this problem by providing a way for us to intercept a `ref` and forward it as a normal prop:
`embed:16-3-release-blog-post/forward-ref-example.js`
## Component Lifecycle Changes
React's class component API has been around for years with little change. However, as we add support for more advanced features (such as [error boundaries](/docs/react-component.html#componentdidcatch) and the upcoming [async rendering mode](/blog/2018/03/01/sneak-peek-beyond-react-16.html)) we stretch this model in ways that it was not originally intended.

2
examples/16-3-release-blog-post/create-ref-example.js

@ -9,6 +9,6 @@ class MyComponent extends React.Component {
componentDidMount() {
// highlight-next-line
this.divRef.value.focus();
this.divRef.current.focus();
}
}

32
examples/16-3-release-blog-post/fancy-button-example.js

@ -0,0 +1,32 @@
class FancyButton extends React.Component {
buttonRef = React.createRef();
focus() {
this.buttonRef.current.focus();
}
render() {
// highlight-next-line
const {label, theme, ...rest} = this.props;
// highlight-range{4}
return (
<button
{...rest}
className={`${theme}-button`}
ref={this.buttonRef}>
{label}
</button>
);
}
}
// highlight-next-line
const FancyThemedButton = withTheme(FancyButton);
// We can render FancyThemedButton as if it were a FancyButton
// It will automatically receive the current "theme",
// And the HOC will pass through our other props.
<FancyThemedButton
label="Click me!"
onClick={handleClick}
/>;

34
examples/16-3-release-blog-post/forward-ref-example.js

@ -0,0 +1,34 @@
function withTheme(Component) {
// highlight-next-line
function ThemedComponent({forwardedRef, ...rest}) {
// highlight-range{6}
return (
<ThemeContext.Consumer>
{theme => (
<Component
{...rest}
ref={forwardedRef}
theme={theme}
/>
)}
</ThemeContext.Consumer>
);
}
// Intercept the "ref" and pass it as a custom prop.
// highlight-range{1-3}
return React.forwardRef((props, ref) => (
<ThemedComponent {...props} forwardedRef={ref} />
));
}
// highlight-next-line
const fancyButtonRef = React.createRef();
// fancyButtonRef will now point to FancyButton
// highlight-range{4}
<FancyThemedButton
label="Click me!"
onClick={handleClick}
ref={fancyButtonRef}
/>;

10
examples/16-3-release-blog-post/hoc-theme-example.js

@ -0,0 +1,10 @@
function withTheme(Component) {
return function ThemedComponent(props) {
// highlight-range{2-4}
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}
Loading…
Cancel
Save