[译]深入理解React中的函数组件与类组件

在React世界中,有两种编写React组件的方式。 一个使用函数,另一个使用类。 最近,函数组件变得越来越流行,那为什么呢?

本文将通过示例代码遍历每个组件,从而帮助您了解函数组件和类组件之间的区别,以便您可以深入了解现代React!

渲染JSX

首先,明显的区别是语法。就像它们的名称一样,函数组件只是返回JSX的普通JavaScript函数。类组件是一个JavaScript类,它扩展了具有render方法的React.Component。有点混乱?让我们看一个简单的例子。

import React from "react";
 
const FunctionalComponent = () => {
 return 

Hello, world

; };

如您所见,函数组件是返回JSX的函数。如果您不熟悉ES6中引入的箭头功能,也可以不使用以下示例进行检查。

import React from "react";

function FunctionalComponent() {
 return 

Hello, world

; }

在CodePen中查看带有函数组件的渲染

另一方面,在定义类组件时,您必须创建一个扩展React.Component的类。要渲染的JSX将在render方法内返回。

import React, { Component } from "react";

class ClassComponent extends Component {
 render() {
   return 

Hello, world

; } }

以下是相同的示例,但未使用解构。如果您不熟悉解构,则可以了解有关ES6中引入的解构和箭头功能的更多信息!

import React from "react";

class ClassComponent extends React.Component {
 render() {
   return 

Hello, world

; } }

在CodePen中查看带有类组件的渲染

传递props

传递props可能会造成混淆,但是让我们看看它们是如何在类和函数组件中编写的。 假设我们正在传递名称为“ Shiori”的道具,如下所示。


const FunctionalComponent = ({ name }) => {
 return 

Hello, {name}

; };

在函数组件内部,我们将props作为函数的参数传递。 请注意,我们在这里使用解构。 另外,我们也可以不编写它。

const FunctionalComponent = (props) => {
 return 

Hello, {props.name}

; };

在这种情况下,您必须使用props.name而不是name。

在CodePen中查看具有函数组件的props

class ClassComponent extends React.Component {
  render() {
    const { name } = this.props;
    return 

Hello, { name }

; } }

由于这是一个类,因此您需要使用它来引用props。 当然,我们可以在使用基于类的组件的同时使用分解来获取props内部的名称。

在CodePen中查看具有类组件的props

处理状态

现在我们都知道,我们无法避免在React项目中处理状态变量。 处理状态直到最近才在类组件中可行,但是从React 16.8开始,React Hook useState被引入,以允许开发人员编写有状态的函数组件。 您可以从官方文档中了解有关挂钩的更多信息。 在这里,我们将创建一个从0开始的简单计数器,单击按钮将使计数增加1。

函数组件中状态的处理

const FunctionalComponent = () => {
 const [count, setCount] = React.useState(0);

 return (
   

count: {count}

); };

要在函数组件中使用状态变量,我们需要使用useState Hook,它使用初始状态的参数。 在这种情况下,我们从0次点击开始,因此count的初始状态将为0。

当然,您可以有更多的初始状态,包括null,字符串甚至对象-JavaScript允许的任何类型! 在左侧,当useState返回当前状态和更新状态的函数时,我们正在像这样破坏数组。 如果您对数组的两个元素有些困惑,可以将它们视为状态及其设置器。 在此示例中,我们将它们命名为count和setCount,以使其易于理解两者之间的联系。

在CodePen中查看带有函数组件的状态

类组件中的状态处理

class ClassComponent extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     count: 0
   };
 }

 render() {
   return (
     

count: {this.state.count} times

); } }

想法仍然是相同的,但是类组件在处理状态方面有所不同。首先,我们需要了解React.Component构造函数的重要性。这是官方文档中的定义:

“ React组件的构造函数在挂载之前被调用。为React.Component子类实现构造函数时,应在其他任何语句之前调用super(props)。否则,this.props将在构造函数中未定义,这可能会导致错误。”

基本上,在不实现构造函数和调用super(props)的情况下,您要使用的所有状态变量都是未定义的。因此,让我们先定义构造函数。在构造函数内部,您将创建一个带有状态键和初始值的状态对象。在JSX内部,我们使用this.state.count来访问在构造函数中定义的状态键的值以显示计数。设置器几乎相同,只是语法不同。

另外,您可以编写一个onClick函数。请记住,setState函数接受状态参数,如果需要,则使用props(可选)。

onClick={() =>
  this.setState((state) => {
    return { count: state.count + 1 };
  })
}

在Codepen中查看带有类组件的状态

生命周期方法

最后,让我们谈谈生命周期。 等等,我们快到了! 如您所知,生命周期在渲染时间中起着重要作用。 对于那些从类组件迁移到函数组件的人,您一定想知道什么可以替代类组件中的生命周期方法,例如componentDidMount()。 是的,有一个挂钩可以完美地用于此目的,让我们来看看!

在安装时(componentDidMount)

在第一个渲染完成后立即调用生命周期方法componentDidMount。 过去曾经有一个componentWillMount发生在第一次渲染之前,但是它被认为是旧的,不建议在新版本的React中使用。

const FunctionalComponent = () => {
 React.useEffect(() => {
   console.log("Hello");
 }, []);
 return 

Hello, World

; };

替换componentDidMount,我们将useEffect挂钩与[]的第二个参数一起使用。 useState挂钩的第二个参数通常是一个更改状态的数组,并且仅在这些选定更改上才会调用useEffect。 但是,当它是一个空数组(如本例)时,将在安装时被调用一次。 这是componentDidMount的完美替代。

class ClassComponent extends React.Component {
 componentDidMount() {
   console.log("Hello");
 }

 render() {
   return 

Hello, World

; } }

基本上相同的事情在这里发生:componentDidMount是一个生命周期方法,在第一次渲染之后被调用一次。

卸载时(componentWillUnmount)

const FunctionalComponent = () => {
 React.useEffect(() => {
   return () => {
     console.log("Bye");
   };
 }, []);
 return 

Bye, World

; };

我很高兴地告诉您,我们也可以使用useState挂钩进行卸载。 但请注意,语法有些不同。 您需要做的是返回一个在useEffect函数内卸载时运行的函数。 当您必须清理诸如clearInterval函数之类的订阅时,此功能特别有用,否则可能会导致较大项目上的严重内存泄漏。 使用useEffect的优点之一是我们可以在同一位置编写用于安装和卸载的函数。

class ClassComponent extends React.Component {
 componentWillUnmount() {
   console.log("Bye");
 }

 render() {
   return 

Bye, World

; } }

在Codepen中查看具有函数组件的生命周期

在Codepen中查看带有类组件的生命周期

结论

两种风格都有优点和缺点,但我想得出一个结论,在可预见的将来函数组件将取代现代React。

正如我们在示例中所注意到的,函数组件被编写得更短,更简单,这使得开发,理解和测试变得更加容易。类组件也可能使它的许多用法感到困惑。使用函数组件可以轻松避免此类混乱并保持一切清洁。

还应该注意的是,React团队正在为功能组件提供更多的React钩子,以替换甚至改进类组件。为了跟进,React团队在早期提到,他们将通过避免不必要的检查和内存分配来优化函数组件的性能。听起来听起来很有希望,但是最近为函数组件(例如useState或useEffect)引入了新的挂钩,同时也保证它们不会过时的类组件。团队正在寻求在较新的情况下逐渐采用带有钩子的函数组件,这意味着无需将利用类组件的现有项目切换到函数组件的整个重写过程,以使它们保持一致。

同样,React中有很多有效的编码样式。但是出于上述原因,我更喜欢使用函数组件而不是类组件。我希望本文能帮助您更熟悉现代React。要了解更多信息,请查阅官方文档!您也可以查看有关构建Twilio Video应用程序的文章,了解带挂钩的函数组件的实际使用。

Shiori Yamazaki是Platform Experience团队的一名软件工程实习生。她喜欢开发现代的Web应用程序。可以通过twilio.com或LinkedIn上的syamazaki与她联系。

参考

  • 原文地址
  • 译文地址

你可能感兴趣的:(react)