React 16: What’s New in Life of a Component?

Last Updated on: July 10, 2020

React 16: What’s New in Life of a Component?

As we all know React is all about its components and as developers we are constantly trying to make them reusable and extremely small to make our code efficient and superfluous. Our components should be standalone and smart enough to manage the state and props updates independently.

The two new life-cycle methods introduced with React 16.2 does exactly that and provides power to our components. Before getting into the new methods let’s have a closer look to the updates and management of mostly used life-cycle methods.

 

Revisiting commonly used life-cycle methods

1. shouldComponentUpdate() —

shouldComponentUpdate(nextProps, nextState)

This method lets you decide when to re-render the component by simply returning true or false. You have the control to re-render your app in case of any new props are received or any state changes. Usually a condition is specified to check if the nextProps are different from the current state, if the specified condition evaluates to true, the component will re-render and if it returns false then the component won’t have any effect.

In case of large number of API calls and huge amount of elements rendering into the DOM for a small change, it affects the user experience if no activity happens in your application. To avoid this we mostly use a ‘loading state’ which is usually managed by a rotating spinner, but for how long? what if there are many cascaded promises which never gets completed?

So to increase the performance and prevent unnecessary updates of your components, this method must be used in your components to manage state updates and here’s a surprise —

The concept of PureComponent introduced with React 16 provides the shouldComponentUpdate to be invoked in the background for you.

class MyTextField extends React.PureComponent {}

You don’t need to explicitly identify when the app should be re-rendered to reflect those changes. The PureComponent does a shallow comparison between this.props and nextProps or this.state and nextState

“It is not recommended to have a deep comparison between state or props using methods like JSON.stringify() in shouldComponentUpdate due to performance issues.”

2. componentDidMount() — componentDidMount()

Called just after a component is mounted/rendered. Most appropriate place to load or pre-populate your data from a certain end point and make network related requests.

It can also be used to re-render your app by using setState method. The essence of this method is that the intermediate state in between the callback from the asynchronous setState method is not visible to the user.

This same essence sometimes lead to performance issues if not used correctly as using setState will guarantee to re-render the app and the app may get stuck if the setState callback is erroneous. But don’t worry, in case of modal or tooltip insertions into the DOM, this is the best possible way to manage the app state.

3. componentWillMount() / UNSAFE_componentWillMount() —

componentWillMount() or UNSAFE_componentWillMount()

This method is invoked just before our component is mounted on the DOM, i.e it is only invoked once, just before the initial rendering of the app.

Mostly suited if any element should be mounted in the DOM before the actual app gets mounted. Which gives you the power to show a pop-up or subscription as soon as the component is injected. Then why it has been marked UNSAFE? Nothing will go wrong if you still use this method for setting your app state before mounting it’s just that it has become needless, we can carry out these pre-mounting actions in other possible ways and there are certain pitfalls with componentWillMount () —

  1. Initialize the state in the constructor itself.
  2. Never use it for API calls, the asynchronous data fetching requests may initiate multiple times and multiple renders may hinder the user experience, use componentDidMount instead.
  3. Do not subscribe any actions here, because in case if the mounting fails then componentWillUnmount() will never be executed.
  4. Using setState() here will not trigger a re-rendering of the app because the component for which we are setting the state is not being mounted yet.

4. componentWillReceiveProps() / UNSAFE_componentWillReceiveProps() —

componentWillReceiveProps(nextProps) or UNSAFE_componentWillReceiveProps(nextProps)

Mostly used to get new/updated props from parent components on updating the current state. If you are using middle-wares like Redux or Mobx or managing form field validations or submission, we often use componentWillReceiveProps() to get the new props and update our app state which actually works fine, the reasons for making it UNSAFE are —

  • React only does a shallow comparison of the instances, i.e the old prop and new prop is compared with a triple-equals-equal reference which implies that both are same physical objects even though the values inside are not same. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison – but this can be prohibitively expensive for large data structures.
  • The data prop may contain reference to some function which could change the values of the data prop and React will not be aware of this update and doesn’t have a copy of the intermediate values.
  • The data prop may contain reference to an object which could re-initialize values of the data prop and again without deep comparison React treats both the old and new props as same.

(A => B) !=> (B => A) problem best explains the side effects.

5. componentWillUpdate() / UNSAFE_componentWillUpdate() —

componentWillUpdate(nextProps, nextState) or UNSAFE_componentWillUpdate(nextProps, nextState)

This method is invoked whenever a re-render is required, it is similar to componentWillMount() but setState() can’t be called here as after setState componentWillUpdate will be invoked again and it will lead to an infinite loop.

It’s a misconception that the app state will not get updated inside componentDidUpdate in fact React first setState for the app and then flushes the component from the DOM, the same thing happens with componentDidMount . Since componentWillUpdate is similar in terms of execution to componentWillMount and componentWillReceiveProps combined, the new method getDerivedStateFromProps() does the job safely.

New life-cycle methods in action

 

  1. static getDerivedStateFromProps —static getDerivedStateFromProps(props, state)As clear from the component life-cycle model above, the getDerivedStateFromProps method is called just before the render. The keyword static is essential over here, which explains that this method is invoked by the class not by it’s instance which means any reference of ‘this’ is not accessible inside this method. So, the static keyword must be used in the declaration
    .Unlike other life-cycle methods which can return any desired values like objects or functions etc. getDerivedStateFromProps method only returns any valid state object or null. This method is invoke at the time of initial rendering as well as on subsequent updates. So, it is guaranteed to get executed which makes it a replacement for componentWillReceiveProps as it doesn’t depend on any other factors to get invoked. This is a powerful update to React components, as it makes them more smart and independent.In getDerivedStateFromProps you can perform the calculations and produce any side-effect based on the calculation result inside componentDidUpdate(), the combination of these two makes almost all state updates of your component possible.There are certain pitfall remains because this method may be used in an incorrect way or someone may find any unexpected behavior because of certain uncommitted DOM updates. To prevent such unintentional code breaks we do have getSnapshotBeforeUpdate() to the rescue.
  2. getSnapshotBeforeUpdate —getSnapshotBeforeUpdate(prevProps, prevState)This method is invoked just before the most recent state changes gets updated to the DOM.React 16: What's New in Life of a Component?It stores the current state of your app and resume it exactly after the updates are being made, which can be used to make network requests in the background without affecting the user experience.getSnapshotBeforeUpdate takes the snapshot of the current appstate and after the commit phase, this ‘snapshot’ is passed as a third parameter to the componentDidUpdate method.componentDidUpdate(prevProps, prevState, snapshot) This combination makes it a replacement for componentWillUpdate method and make our components even more powerful. This feature could be used to avoid latency while scrolling to a large list of dynamically fetched data.

    Takeaways

    > Use React.PureComponent to prevent unnecessary updates.

    > Make smart and standalone components to improve reusability.

    > Do not compensate on using UNSAFE methods instead of the new methods as they will be deprecated with React 17.

    > The two new methods are capable of performing every state update irrespective of the cause.

    > Advance concepts like Context API could also be used to provide global state to be consumed by specific child components, to get rid of unnecessary passing of props down the components hierarchy.

Ayush Sharma

July 25, 2018

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *