Will a stateless component re-render if its props have not changed?

Reactjs

Reactjs Problem Overview


One thing I had learned about React is that if the props to a component don’t change, then React doesn’t bother re-rendering the component. Is that true for stateless components too? Or do they behave more like “stupid” functions and get executed every time?

For example, if I had:

import StatelessComponent from '../StatelessComponent';

export default class DocumentsTable extends React.Component {
  state = {
    something: 'foobar',
  };

  render() {
    return (
      <div>
        { this.state.something }
        <StatelessComponent theOnlyProp='baz'>
      </div>
    )
  }
};

When this.state.something updates its value, does <StatelessComponent> get re-rendered? Or is it “smart” enough to see that its props didn’t change, like other React components?

Reactjs Solutions


Solution 1 - Reactjs

UPDATE 25.10.2018

Since React 16.6, you can use React.memo for functional components to prevent re-render, similarly to PureComponent for class components:

const MyComponent = React.memo((props) => {
  return (
    /* markup */
  );
});

Also, memo does internal optimization.

> And unlike a userland memo() higher-order component implementation, the one built into React can be more efficient by avoiding an extra component layer. > Blockquote


OLD ANSWER

Yes, they always re-render 1 (unless you use React.memo as explained above) if setState() is called in the component itself or one of its parents, because functional stateless components don't carry a shouldComponentUpdate. In fact, each React component is being re-rendered1 unless they implement shouldComponentUpdate.


Important to note is that calling render() doesn't mean that DOM Nodes are being manipulated in any way. The render method just serves the diff algorithm to decide which DOM Nodes need to really be attached / detached. Note that render() is not expensive, it's the DOM manipulations that are expensive. They are executed only if render() returns different virtual trees.

From React's documentation

> Just to be clear, rerender in this context means calling render for all components, it doesn’t mean React will unmount and remount them. It will only apply the differences following the rules stated in the previous sections.

Just don't worry and let render() be called unless your component is huge, then you're better off with stateful Component that implements shouldComponentUpdate().

Look here for an interesting discussion.

1 means that render() function of the component is called, not that the underlying DOM node is being manipulated.

Solution 2 - Reactjs

See react does not only rerenders only If props are changed it even rerenders itself if any state change is there. In your case the component will rerender as your state is changing. The way react works is based on an algorithm named Reconciliation, what this algorithm does is that it compares your virtual DOM with real DOM and if it sees any change then it rerender your actual DOM by replacing it with your virtual DOM so any change in state will cause rerendering of the whole component.

Solution 3 - Reactjs

>Will a Stateless component re-render if its props have not changed?

Yes. Stateless render function will be called even if nothing has changed. However, React will in the reconciliation phase compare the virtual DOM (generated by the render function) against the existing DOM. This is far in the pipeline, hence not ideal if the render function was costly to compute.

A Pure component does have a default shallow comparison of the property and would have stopped the render to be executed. See the Pure component as a normal class React component that has a shouldComponentUpdate that compare with a triple equal the existing properties and the new one.

That being said, you can wrap your Stateless component into a Pure Component by using Recompose.pure (https://github.com/acdlite/recompose/blob/master/docs/API.md#pure) which will automatically perform, like the Pure Component, a shallow comparison without compromising on the short syntax of the Stateless component.

import StatelessComponent from '../StatelessComponent';   
const PureChildFromStatelessComponent = Recompose.pure(StatelessComponent);
// ... 
<PureChildFromStatelessComponent ... />

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3812429View Question on Stackoverflow
Solution 1 - ReactjsLyubomirView Answer on Stackoverflow
Solution 2 - ReactjsAniruddh AgarwalView Answer on Stackoverflow
Solution 3 - ReactjsPatrick DesjardinsView Answer on Stackoverflow