Home > Article > Web Front-end > Why react recommends function components
Reason: 1. Function component syntax is shorter and simpler, which makes it easier to develop, understand and test; 2. Excessive use of this in class components makes the entire logic look confusing; 3. Hooks The function only supports function components; 4. The React team has made more optimizations for function components to avoid unnecessary checks and memory leaks; 5. Functional components have low performance consumption because functional components do not need to create instances and render Just execute it when you get the returned react element and destroy all the intermediate amounts directly.
#The operating environment of this tutorial: Windows7 system, react18 version, Dell G3 computer.
When developing using the React framework, there are two ways to create components, using functions and using classes. Currently, function components are becoming more and more popular. The following uses examples to analyze the differences between functional components and class components, and summarizes the reasons (advantages) for using functional components.
Function components and class components process JSX differently. Just like their names, the function component is a pure Javascript function, directly Returns JSX; the class component is a Javascript class that extends React.Component
and implements the render method, which returns JSX. The following is an example:
import React from "react";
const FunctionalComponent = () => {
return <h1>Hello, world</h1>;
};
The above defines a function component in the form of an ES6 arrow function, and the function body directly returns JSX. If you are not familiar with arrow functions, you can also write them in the following form:
import React from "react";
function FunctionalComponent() {
return <h1>Hello, world</h1>;
}
The two writing methods are the same.
Then, let’s take a look at how to define a class component. First we need to extend React.Component
, and then return JSX in the render method. See the following code snippet for details:
import React, { Component } from "react";
class ClassComponent extends Component {
render() {
return <h1>Hello, world</h1>;
}}
The above uses the ES6 destructuring assignment syntax to import the module. If you are not familiar with the destructuring assignment syntax, you can also write it in the following form, which will look more concise:
import React from "react";
class ClassComponent extends React.Component {
render() {
return <h1>Hello, world</h1>;
}
}
When we need to pass data to a component, we use props, such as<FunctionalComponent name="Shiori" />
, name is a props attribute of Component, there can be more attributes here. The functional form of the FunctionalComponent component is defined as follows:
const FunctionalComponent = ({ name }) => {
return <h1>Hello, {name}</h1>;
};
Or do not use destructuring assignment
const FunctionalComponent = (props) => {
return <h1>Hello, {props.name}</h1>;
};
In this way, you need to use props.name
To get the name attribute.
Then, let’s take a look at how class components use props,
class ClassComponent extends React.Component {
render() {
const { name } = this.props;
return <h1>Hello, { name }</h1>;
}}
In class components, you need to use this
to get props, You can then use destructuring assignment to get the name
attribute.
In React projects, we inevitably have to deal with state variables. Class components did not support handling state until recently. However, starting from React version 16.8, function components support the hook method useState
, so that we can easily use state variables in function components. The following uses a counter counter example to illustrate their differences.
const FunctionalComponent = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<p>count: {count}</p>
<button onClick={() => setCount(count + 1)}>Click</button>
</div>
);};
The useState
hook is used here, which receives an initial state as a parameter. In this case, the counter starts at 0, so we give count an initial value of 0.
The initial value of state supports various data types, including null, string or object objects, as long as it is allowed by javascript. On the left side of =
, we use the form of destructuring assignment to accept the return value of useState, including the current state variable and the setter function that updates the variable, namely count
and setCount
.
class ClassComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>count: {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click
</button>
</div>
);
}}
与函数组件大同小异,首先我们要理解React.Component
的构造函数constructor
,react的官方文档对constructor的定义如下:
“The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.”
翻译一下,
React组件的constructor方法会在组件完全加载完成之前调用。在constructor方法中,你需要在第一行调用super(props),否则会报this.props是undefined的错误。
如果在类组件中,你没有实现constructor方法并调用super(props),那么所有的状态变量都将是undefined。所以,别忘记先定义constructor方法,在constructor方法中,我们需要给this.state一个初始值,像上面的代码那样。然后我们可以在JSX中使用this.state.count
来获取count的值,setter的使用也是类似的。
这里先定义一个onClick
方法,后面会用到,
onClick={() =>
this.setState((state) => {
return { count: state.count + 1 };
})}
这里注意setState()方法接收的是个箭头函数,而箭头函数的参数是state和props,props是可选的,这里没用到就没写。
React的组件在它整个的渲染的过程中,有它的生命周期。如果你之前一直使用类组件,刚刚接触函数组件,你可能会疑惑,为什么在函数组件中没有componentDidMount()
这类的生命周期方法?但是别急,有其他的钩子函数可以使用。
类组件的生命周期函数componentDidMount
会在首次渲染完成之后调用。首次渲染完成之前会调用componentWillMount
,但是这个方法在新版本的React中不推荐使用了。
在函数组件中,我们使用useEffect
钩子函数来处理生命周期内的事件,像下面这样,
const FunctionalComponent = () => {
React.useEffect(() => {
console.log("Hello");
}, []);
return <h1>Hello, World</h1>;};
useEffect
有两个参数,第一个是箭头函数,第二个是[]
,[]
里面是变化的state(s)
。什么意思呢?就是[]
中的状态变化了,箭头函数会被调用。如果像现在这样写个[]
,那箭头函数只会在组件第一次渲染之后调用一次,其功能类似下面类组件的componentDidMount
。
class ClassComponent extends React.Component {
componentDidMount() {
console.log("Hello");
}
render() {
return <h1>Hello, World</h1>;
}}
const FunctionalComponent = () => {
React.useEffect(() => {
return () => {
console.log("Bye");
};
}, []);
return <h1>Bye, World</h1>;};
这里注意return的也是一个箭头函数,这个函数就是在卸载阶段执行的。当你需要执行一些卸载操作,可以放在这里,比如你可以把clearInterval放在这里,避免内存泄漏。使用useEffect钩子函数的最大好处就是可以把加载函数和卸载函数放在一个同一个地方。这里对比一下类组件的写法:
class ClassComponent extends React.Component {
componentWillUnmount() {
console.log("Bye");
}
render() {
return <h1>Bye, World</h1>;
}}
函数组件和类组件各有优缺点,但函数组件相比类组件的优势:
函数组件语法更短、更简单,这使得它更容易开发、理解和测试;而类组件也会因大量使用 this而让人感到困惑
类组件过多的使用this
让整个逻辑看起来很混乱;
React团队主推的React hooks功能也只支持函数组件;
注:React团队也在努力将hooks功能引入类组件,所以没必要将现有的类组件都改写成函数组件;
类组件的性能消耗比较大,因为类组件需要创建类组件的实例,而且不能销毁。
函数式组件性能消耗小,因为函数式组件不需要创建实例,渲染的时候就执行一下,得到返回的react元素后就直接把中间量全部都销毁。
The above is the detailed content of Why react recommends function components. For more information, please follow other related articles on the PHP Chinese website!