search
HomeWeb Front-endJS TutorialOptimizing React Performance with Stateless Components

Optimizing React Performance with Stateless Components

Optimizing React Performance with Stateless Components

This article explores stateless components in React. This type of component does not contain this.state = { ... } calls, and only processes incoming "props" and child components.

Summary of key points

  • The stateless component in React does not contain any this.state = { … } calls. They only handle incoming "props" and subcomponents, which makes them simpler and easier to analyze from a test perspective.
  • Stateless components can be converted into functional components, which is more like pure JavaScript and has less dependence on the framework used.
  • The performance of stateless components can be optimized by using React.PureComponent, which has a built-in shouldComponentUpdate method that allows for shallow comparisons of each prop.
  • Recompose is a utility library for function components and advanced components in React. It can be used to render function components without re-rendering when props are unchanged.
  • Stateless components can significantly improve the performance of React applications because they do not manage their own state or lifecycle methods, thus reducing code volume and memory consumption. However, they also have some limitations, such as not being able to use lifecycle methods or managing their own state.

Basics

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}

The code runs normally. It's very basic, but it builds examples.

It should be noted:

  • It is stateless, without this.state = { ... }.
  • console.log is used to understand its usage. Especially when performing performance optimization, if props are not actually changed, unnecessary re-rendering needs to be avoided.
  • The event handler here is "inline". This syntax is convenient because its code is close to the elements it processes, and this syntax means you don't need to do anything .bind(this).
  • Using such an inline function will have a little performance loss, because the function must be created every time it is rendered. This will be detailed later.

Display component

We now realize that the above component is not only stateless, it is actually what Dan Abramov calls a display component. It's just a name, but basically, it's lightweight, produces some HTML/DOM and doesn't handle any state data.

So we can make it into a function! Not only does this feel "cool", it also makes it less terrible because it's easier to understand. It receives input and, independently of the environment, always returns the same output. Of course, it "callback" because one of the props is a callable function.

Let's rewrite it:

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}

It feels good, right? It feels like pure JavaScript, you can write it without thinking about the framework you are using.

The problem of continuous re-rendering

Suppose our User component is used in a component that changes state over time. But the state does not affect our components. For example, like this:

const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}

Run this code and you will notice that even if nothing changes, our components will be re-rendered! This is not a big problem now, but in practical applications, components tend to become more and more complex, and every unnecessary re-rendering will cause the website to slow down.

If you use react-addons-perf to debug this application now, I'm sure you will find that time is wasted on rendering Users->User. Oops! what to do? !

It seems that everything is showing that we need to use shouldComponentUpdate to cover how React thinks props are different, and we are sure they are not different. In order to add a React lifecycle hook, the component needs to be a class. Alas. So we go back to the original class-based implementation and add a new lifecycle hook method:

Back to class component

import React, { Component } from 'react'

class Users extends Component {
  constructor(props) {
    super(props)
    this.state = {
      otherData: null,
      users: [{name: 'John Doe', highlighted: false}]
    }
  }

  async componentDidMount() {
    try {
      let response = await fetch('https://api.github.com')
      let data = await response.json()
      this.setState({otherData: data})
    } catch(err) {
      throw err
    }
  }

  toggleUserHighlight(user) {
    this.setState(prevState => ({
      users: prevState.users.map(u => {
        if (u.name === user.name) {
          u.highlighted = !u.highlighted
        }
        return u
      })
    }))
  }

  render() {
    return <div>
      <h1 id="Users">Users</h1>
      {
        this.state.users.map(user => {
          return <User
            name={user.name}
            highlighted={user.highlighted}
            userSelected={() => {
              this.toggleUserHighlight(user)
            }}/>
         })
      }
    </div>
  }
}

Pay attention to the newly added shouldComponentUpdate method. This is a bit ugly. Not only can we no longer use functions, but we also have to manually list props that may be changed. This involves a bold assumption that the userSelected function prop will not change. This is unlikely, but it needs attention.

But please note that even if the included App component is re-rendered, this will only be rendered once! So, this is good for performance. But can we do better?

React.PureComponent

Since React 15.3, there is a new component base class. It's called PureComponent, and it has a built-in shouldComponentUpdate method that makes a "shallow comparison" of each prop. marvelous! If we use this we can discard our custom shouldComponentUpdate method which must list specific props.

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}

Try it and you will be disappointed. It re-renders every time. Why? ! The answer is because the userSelected function is recreated every time in the App's render method. This means that when a PureComponent-based component calls its own shouldComponentUpdate(), it returns true, because the function is always different, because it is created every time.

Usually, the solution to this problem is to bind the function in the constructor that contains the component. First, if we do this, it means we have to type the method name 5 times (and 1 before):

  • this.userSelected = this.userSelected.bind(this) (in the constructor)
  • userSelected() { ... } (as the method definition itself)
  • <user ... userselected="{this.userSelected}"></user> (where the rendering of the User component is defined)

Another problem is that, as you can see, when the userSelected method is actually executed, it depends on a closure. In particular, it relies on the scope variable this.state.users.map() from the iterator. user

Admittedly, there is a solution to this problem, which is to first bind the

method to userSelected and then when the method is called (in a child component), pass the this (or its name) go back. Here is a solution like this. user

recompose to rescue!

First, let's review our goals:

  1. Writing functional components feels better because they are functions. This immediately tells the code reader that it does not save any state. They are easy to reason from a unit test perspective. And they feel more concise and more like pure JavaScript (and of course JSX).
  2. We are too lazy to bind all methods passed to child components. Of course, if the methods are complex, it is better to refactor them instead of creating them dynamically. Dynamic creation methods mean we can write their code directly where they are used, we don't have to name them, nor have we mentioned them 5 times in three different places.
  3. Subcomponents should be re-rendered only when props change. This may not matter for small and fast components, but for practical applications, when you have many of these components, all of these extra renderings waste CPU when can be avoided.
(In fact, our ideal situation is that the component is rendered only once. Why can't React solve this problem for us? In that case, the "How to Make React Faster" blog posts will be reduced by 90%.)

According to the documentation, recompose is "a library of React utility tools for function components and advanced components. Think of it as a lodash for React."

. There are a lot to explore in this library, but now we want to render our function components without re-rendering when props have not changed. The first time we tried rewriting it back to the function component with recompose.pure, it looks like this:

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}

You may notice that if you run this code, the User component will still re-render even if the props (

and

keys) have not changed. name highlightedLet's go a step further. We don't use

, but we use

, which is a version of recompose.pure, but you can specify the prop key you want to focus on: recompose.onlyUpdateForKeys recompose.pure

const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}

After running this code, you will notice that it will only be updated when

or

props change. If the parent component is re-rendered, the User component does not. name highlightedLong live! We found gold!

Discussion

First, ask yourself if it's worth optimizing your component performance. Maybe that's more than it's worth it. Your components should be lightweight, maybe you can move any expensive calculations out of the components and move them into external memorable functions, or you can reorganize your components so that some data cannot be No waste of rendering components when used. For example, in this example, you may not want to render the User component before fetch is done.

Writing the code in the most convenient way for you, then starting your program and iterating from there to make it perform better is not a bad solution. In this example, in order to improve performance, you need to define the function component from:

import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
         onClick={event => {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}

…changed to…

const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}}
       onClick={event => {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}

Ideally, rather than showing a way to bypass the problem, the best solution is a new patch from React, which makes a huge improvement to shallowEqual to "automatically" identifying the incoming and comparing is a function, and just because it is not equal does not mean that it is actually different.

Agree! There is a compromise alternative to having to deal with inline functions that bind methods in the constructor and each recreation. That is the public class field. It is a phase 2 feature in Babel, so your setup will likely support it. For example, here is a branch that uses it, which is not only shorter, but now also means we don't need to list all non-function props manually. This solution must abandon closures. Nevertheless, it is still good to know and realize recompose.onlyUpdateForKeys when needed.

For more information about React, please check out our course "React The ES6 Way".

This article was peer-reviewed by Jack Franklin. Thanks to all SitePoint peer reviewers for making SitePoint’s content perfect!

Frequently Asked Questions about Optimizing React Performance with Stateless Components

What is the main difference between a stateful component and a stateless component in React?

State components (also known as class components) maintain memory about the changes in component state over time. They are responsible for how components behave and render. On the other hand, stateless components (also called functional components) do not have their own state. They receive data from the parent component in the form of props and render it. They are mainly responsible for the UI part of the component.

How to optimize the performance of my React application using stateless components?

Stateless components can significantly improve the performance of React applications. Since they do not manage their own state or lifecycle methods, they have less code, which makes them easier to understand and test. They can also reduce the amount of memory consumed by the application. To optimize performance, you can convert state components to stateless components as much as possible and use React's PureComponent to avoid unnecessary re-rendering.

What is PureComponent and how does it help optimize React performance?

PureComponent is a special React component that helps optimize the performance of your application. It uses shallow prop and state comparison to implement the shouldComponentUpdate lifecycle method. This means it will re-render only when the state or props change, which can significantly reduce unnecessary re-rendering and improve performance.

How to convert a state component in React to a stateless component?

Converting a state component to a stateless component includes removing any state or lifecycle method from the component. The component should only receive data through props and render it. Here is an example:

// Status component class Welcome extends React.Component { render() { return

Hello, {this.props.name}
; } }

// Stateless Component function Welcome(props) { return

Hello, {props.name}
; }

What are the best practices for using stateless components in React?

Some best practices for using stateless components in React include: use as many of them as possible to improve performance and readability; keep them small and focus on a single function; and avoid using state or lifecycle methods. It is also recommended to use props deconstruction to write cleaner code.

Can stateless components use lifecycle methods in React?

No, stateless components cannot use lifecycle methods in React. Lifecycle methods are only applicable to class components. However, with the introduction of Hooks in React 16.8, you can now add state and lifecycle features to function components.

What are the limitations of stateless components in React?

While stateless components have many advantages, they also have some limitations. They cannot use lifecycle methods or manage their own state. However, these limitations can be overcome by using React Hooks.

How can stateless components improve the readability of code?

Stateless components improve code readability through simplicity and clarity. They do not manage their own state or use lifecycle methods, which makes them simpler and easier to understand. They also encourage the use of small, reusable components, which can make the code more organized and easier to maintain.

Can stateless components handle events in React?

Yes, stateless components can handle events in React. Event handlers can be passed as props to stateless components. Here is an example:

function ActionLink(props) { Return ( Click me ); }

How does stateless components promote the modularization of code?

Stateless components promote modularization of code by promoting the use of small, reusable components. Each component can be developed and tested independently, which makes the code easier to maintain and understand. It also encourages separation of concerns, where each component is responsible for a single function.

The above is the detailed content of Optimizing React Performance with Stateless Components. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Replace String Characters in JavaScriptReplace String Characters in JavaScriptMar 11, 2025 am 12:07 AM

Detailed explanation of JavaScript string replacement method and FAQ This article will explore two ways to replace string characters in JavaScript: internal JavaScript code and internal HTML for web pages. Replace string inside JavaScript code The most direct way is to use the replace() method: str = str.replace("find","replace"); This method replaces only the first match. To replace all matches, use a regular expression and add the global flag g: str = str.replace(/fi

How do I create and publish my own JavaScript libraries?How do I create and publish my own JavaScript libraries?Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser?How do I optimize JavaScript code for performance in the browser?Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

How do I debug JavaScript code effectively using browser developer tools?How do I debug JavaScript code effectively using browser developer tools?Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

jQuery Matrix EffectsjQuery Matrix EffectsMar 10, 2025 am 12:52 AM

Bring matrix movie effects to your page! This is a cool jQuery plugin based on the famous movie "The Matrix". The plugin simulates the classic green character effects in the movie, and just select a picture and the plugin will convert it into a matrix-style picture filled with numeric characters. Come and try it, it's very interesting! How it works The plugin loads the image onto the canvas and reads the pixel and color values: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data The plugin cleverly reads the rectangular area of ​​the picture and uses jQuery to calculate the average color of each area. Then, use

How to Build a Simple jQuery SliderHow to Build a Simple jQuery SliderMar 11, 2025 am 12:19 AM

This article will guide you to create a simple picture carousel using the jQuery library. We will use the bxSlider library, which is built on jQuery and provides many configuration options to set up the carousel. Nowadays, picture carousel has become a must-have feature on the website - one picture is better than a thousand words! After deciding to use the picture carousel, the next question is how to create it. First, you need to collect high-quality, high-resolution pictures. Next, you need to create a picture carousel using HTML and some JavaScript code. There are many libraries on the web that can help you create carousels in different ways. We will use the open source bxSlider library. The bxSlider library supports responsive design, so the carousel built with this library can be adapted to any

Enhancing Structural Markup with JavaScriptEnhancing Structural Markup with JavaScriptMar 10, 2025 am 12:18 AM

Key Points Enhanced structured tagging with JavaScript can significantly improve the accessibility and maintainability of web page content while reducing file size. JavaScript can be effectively used to dynamically add functionality to HTML elements, such as using the cite attribute to automatically insert reference links into block references. Integrating JavaScript with structured tags allows you to create dynamic user interfaces, such as tab panels that do not require page refresh. It is crucial to ensure that JavaScript enhancements do not hinder the basic functionality of web pages; even if JavaScript is disabled, the page should remain functional. Advanced JavaScript technology can be used (

How to Upload and Download CSV Files With AngularHow to Upload and Download CSV Files With AngularMar 10, 2025 am 01:01 AM

Data sets are extremely essential in building API models and various business processes. This is why importing and exporting CSV is an often-needed functionality.In this tutorial, you will learn how to download and import a CSV file within an Angular

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft