React16 Highlights

Written byKalanKalan
💡

If you have any questions or feedback, pleasefill out this form

This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.

React has officially released version 16, and the official blog provides a comprehensive (and visually appealing) overview. This article serves as a condensed note and summary of some details.

1. componentDidCatch(error, info)

One of the most exciting features of React 16 is the introduction of Error Boundaries, which ensure that errors during the lifecycle do not affect the entire component. Previously, if an error occurred during rendering, it would cause the entire component to disappear.

The componentDidCatch method will only be called if an error occurs in a lifecycle method, so throwing an error in places like the constructor will not be caught by componentDidCatch.

componentDidCatch receives two parameters: error and info. You can handle errors within componentDidCatch, implement a fallback UI, or call a third-party service to log the error, among other actions.

class Post extends Component {
  constructor() {
    throw new Error("oops") // Will not be caught by componentDidCatch
  }

  componentWillMount() {
    this.setState(state => {
      throw new Error("oops")
      return {}
    })
  }
}
class App extends Component {
  constructor() {
    super(props)
    this.state = {
      post: { content: "" },
    }
  }

  updatePost = () => {
    this.setState(state => ({ ...state, post: null }))
  }

  componentDidCatch(error, info) {
    this.setState({ hasError: true })
    Logger.warn(error, info)
  }

  render() {
    return (
      <div>
        <Post post={this.state.post} />
      </div>
    )
  }
}

In addition to the example above, you can also wrap componentDidCatch using higher-order component techniques, or set up ErrorBoundary components to handle errors for children uniformly.

2. Text-Only component

Unnecessary <span> and react-text nodes have been removed, and you can now directly return strings.

const Text = ({ text }) => {
  return "pure string!"
}
class App extends Component {
  render() {
    return (
      <div>
        <Text /> // Renders 'pure string', rather than <span>pure string</span>
      </div>
    )
  }
}

*3. ReactDOM.createPortal(component, dom)

createPortal is another feature I particularly enjoy. It allows you to render components to different DOM nodes within the Component Tree, completely independent of the children, as shown in the structure below.

<div id="app1"></div>
<div id="app2"></div>
class App extends Component {
  constructor() {}

  render() {
    return (
      <div>
        <h2>Main header</h2>
        {ReactDOM.createPortal(<Sidebar />, document.querySelector("#app2"))}
      </div>
    )
  }
}

With ReactDOM.createPortal() in App, not only does it improve readability (without needing callbacks or directly manipulating the DOM), but it also allows for operations on nodes outside of the children, making it very convenient for writing components like modals that may require overlays. (Overlays are better handled at the root node level.)

4. Custom Attributes

render() {
  return (
  	<div ui-prefix-scroller='foo'>
    </div>
  )
};

5. Prevent Update

Returning null in setState will not trigger an update (unlike previous versions). If you want to avoid updating a component in the future, you can simply pass null.

6. SSR Support

For more details, refer to What's new with server-side rendering in React 16. Notably, React 16 SSR now supports streaming, with renderToNodeStream(Component) returning a stream.

Additionally, the article's author emphasizes:

Please, please, please make sure you always set NODE_ENV to production when using React SSR in production!

Conclusion

These are the main changes in React 16. The official blog provides a more detailed introduction.

If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨

Buy me a coffee