在花了一些时间学习React之后,我明白了创建组件的两种主要范式之间的区别。

我的问题是什么时候应该使用哪个,为什么?其中一种与另一种相比有什么好处/权衡?


ES6签署:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

功能:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

我认为函数是指没有状态可以被那个组件操纵的情况,但真的是这样吗?

我想,如果我使用任何生命周期方法,最好使用基于类的组件。


当前回答

使用functional表单更简单,因为可以重用表单输入字段,还可以使用React显示条件将它们分开。

类是一个不能分解或重用的大组件。它们更适合于功能丰富的组件,比如在弹出式模块中执行算法的组件。

最佳实践是功能组件的可重用性,然后使用小的功能组件来组装完整的部分,例如,表单输入字段导入到React表单的文件中。

另一个最佳实践是在执行此操作的过程中不要嵌套组件。

其他回答

只要可能,总是尝试使用无状态函数(功能组件)。在某些情况下,你需要使用一个常规的React类:

组件需要维护状态 组件重新渲染过多,您需要通过shouldComponentUpdate来控制它 您需要一个容器组件

更新

现在有一个名为PureComponent的React类,你可以扩展(而不是Component),它实现了自己的shouldComponentUpdate,为你处理浅道具比较。阅读更多

在React 17中,术语无状态功能组件是误导性的,应该避免使用。SFC已弃用,Dan Abramov在React.SFC上),它们可以有状态,也可以有钩子(充当生命周期方法),它们或多或少与类组件重叠

基于类的组件

状态 生命周期方法 用React记忆。PureComponent

功能组件:

state (useState, useReducer钩子) 生命周期方法(通过useEffect, useLayoutEffect钩子) 通过备忘录HOC进行记忆

为什么我更喜欢功能性组件

React提供了useEffect钩子,这是一种非常清晰和简洁的方式来组合componentDidMount, componentDidUpdate和componentWillUnmount生命周期方法 使用钩子,您可以提取可以在组件之间轻松共享和可测试的逻辑 减少对范围的混淆

React动机为什么使用钩子(即功能组件)。

我在生产中使用了大量的功能组件。我只在“错误边界”中使用过一次类组件,因为在功能组件中没有可选的“错误边界”。

我只使用了一次“类组件”。

基于类的组件提供了一种更加结构化和有组织的方式来定义和实现组件,并且它们提供了额外的特性和功能,例如使用本地状态和生命周期方法的能力。这可以使它们成为创建需要大量逻辑和功能的复杂组件的好选择。

另一方面,功能组件更简单,更容易使用,而且它们的性能更高,因为它们更轻量级。它们也更容易测试和调试,因为它们是纯函数,没有副作用。这使得它们成为创建不需要大量逻辑或状态管理的简单组件的好选择。

新的回答:在React Hooks出现之前,以下大部分都是正确的。

componentDidUpdate can be replicated with useEffect(fn), where fn is the function to run upon rerendering. componentDidMount methods can be replicated with useEffect(fn, []), where fn is the function to run upon rerendering, and [] is an array of objects for which the component will rerender, if and only if at least one has changed value since the previous render. As there are none, useEffect() runs once, on first mount. state can be replicated with useState(), whose return value can be destructured to a reference of the state and a function that can set the state (i.e., const [state, setState] = useState(initState)). An example might explain this more clearly:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

说句题外话,我听过很多人因为性能原因而讨论不使用功能组件,特别是这个原因

事件处理函数在功能组件的每次渲染中被重新定义

尽管如此,请考虑你的组件是否真的以这样的速度或体积渲染,这将是值得关注的。

如果是,可以使用useCallback和useMemo钩子防止重新定义函数。但是,请记住,这可能会使您的代码(在微观上)性能变差。

但说实话,我从未听说过重新定义函数会成为React应用程序的瓶颈。过早的优化是万恶之源——当它成为一个问题时,要担心这一点。


老回答:你的想法是对的。如果你的组件只包含一些道具和渲染,那就使用功能性组件。您可以将它们看作纯函数,因为给定相同的道具,它们将始终呈现和表现相同。此外,它们不关心生命周期方法或拥有自己的内部状态。

因为它们是轻量级的,所以将这些简单组件编写为功能组件是相当标准的。

如果你的组件需要更多的功能,比如保持状态,请使用类。

更多信息:https://facebook.github.io/react/docs/reusable-components.html#es6-classes