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] 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. 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) [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 ## 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. 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() { componentDidMount() {
// highlight-next-line // 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