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
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:- 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).
- 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.
- 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.
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
highlighted
Let's go a step further. We don't 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
highlighted
Long live! We found gold!
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: …changed to… 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 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 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 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. 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 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 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>
}
}
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>
}
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. recompose.onlyUpdateForKeys
when needed.
What is the main difference between a stateful component and a stateless component in React?
How to optimize the performance of my React application using stateless components?
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?
// Stateless Component function Welcome(props) { return
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!

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

Node.js excels at efficient I/O, largely thanks to streams. Streams process data incrementally, avoiding memory overload—ideal for large files, network tasks, and real-time applications. Combining streams with TypeScript's type safety creates a powe

The differences in performance and efficiency between Python and JavaScript are mainly reflected in: 1) As an interpreted language, Python runs slowly but has high development efficiency and is suitable for rapid prototype development; 2) JavaScript is limited to single thread in the browser, but multi-threading and asynchronous I/O can be used to improve performance in Node.js, and both have advantages in actual projects.

JavaScript originated in 1995 and was created by Brandon Ike, and realized the language into C. 1.C language provides high performance and system-level programming capabilities for JavaScript. 2. JavaScript's memory management and performance optimization rely on C language. 3. The cross-platform feature of C language helps JavaScript run efficiently on different operating systems.

JavaScript runs in browsers and Node.js environments and relies on the JavaScript engine to parse and execute code. 1) Generate abstract syntax tree (AST) in the parsing stage; 2) convert AST into bytecode or machine code in the compilation stage; 3) execute the compiled code in the execution stage.

The future trends of Python and JavaScript include: 1. Python will consolidate its position in the fields of scientific computing and AI, 2. JavaScript will promote the development of web technology, 3. Cross-platform development will become a hot topic, and 4. Performance optimization will be the focus. Both will continue to expand application scenarios in their respective fields and make more breakthroughs in performance.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Zend Studio 13.0.1
Powerful PHP integrated development environment

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),
