Quando usar os componentes React baseados na classe ES6 vs. os componentes funcionais do ES6 React?

212

Depois de passar algum tempo aprendendo o React, entendo a diferença entre os dois principais paradigmas da criação de componentes.

Minha pergunta é quando devo usar qual e por quê? Quais são os benefícios / tradeoffs de um sobre o outro?


Classes ES6:

import React, { Component } from 'react';

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

Funcional:

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

Estou pensando funcional sempre que não há estado a ser manipulado por esse componente, mas é isso?

Suponho que, se eu usar qualquer método de ciclo de vida, talvez seja melhor usar um componente baseado em classe.

omarjmh
fonte
7
Parece que você já sabe a resposta.
Felix Kling19 /
2
Se você tiver um componente apenas com o método de renderização, poderá transformá-lo em forma funcional. Se você precisa de algo mais do que apátrida tornar função, classes de uso
just-boris
2
Para ser ainda mais concisa tente o seguinte:const MyComponent = (props) => <div>...</div>
Viliam Simko
1
Eu nunca uso funcional se puder ser evitado. Porque inevitavelmente, acabo precisando refatorar para classes baseadas na estrada. E, em seguida, muitas vezes precisa refatorar de volta ao funcional depois disso.
keithjgrant
Em 2020, a abordagem correta é usar componentes funcionais sempre que possível, porque eles suportam ganchos e ganchos (em termos de desempenho e arquitetura) são melhores do que as alternativas.
polkovnikov.ph

Respostas:

161

Você tem a ideia certa. Vá com funcional se o seu componente não fizer muito mais do que pegar alguns adereços e renderizar. Você pode pensar nelas como funções puras, porque sempre renderizam e se comportam da mesma forma, considerando os mesmos adereços. Além disso, eles não se preocupam com os métodos do ciclo de vida ou têm seu próprio estado interno.

Por serem leves, escrever esses componentes simples como componentes funcionais é bastante padrão.

Se seus componentes precisarem de mais funcionalidades, como manter estado, use classes.

Mais informações: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


EDIT : Muito do acima foi verdadeiro, até a introdução do React Hooks.

  • componentDidUpdatepode ser replicado com useEffect(fn), onde fné a função a ser executada após a renderização novamente.

  • componentDidMountOs métodos podem ser replicados com useEffect(fn, []), em que fné a função a ser executada após a renderização e []é uma matriz de objetos para a qual o componente será renderizado novamente, se e somente se pelo menos um tiver alterado o valor desde a renderização anterior. Como não há, useEffect()é executado uma vez, na primeira montagem.

  • statepode ser replicado com useState(), cujo valor de retorno pode ser destruído para uma referência do estado e uma função que pode definir o estado (ou seja, const [state, setState] = useState(initState)). Um exemplo pode explicar isso mais claramente:

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

Em relação à recomendação sobre quando usar a classe sobre os componentes funcionais, o Facebook recomenda oficialmente o uso de componentes funcionais sempre que possível . Como um pequeno aparte, ouvi várias pessoas discutindo não usar componentes funcionais pelos motivos de desempenho, especificamente

"As funções de manipulação de eventos são redefinidas por renderização em componentes funcionais"

Embora verdadeiro, considere se seus componentes estão realmente renderizando a uma velocidade ou volume que valeria a pena preocupar.

Se estiverem, você pode impedir a redefinição de funções usando useCallbacke useMemohooks. No entanto, lembre-se de que isso pode piorar seu desempenho (microscopicamente) .

Mas, honestamente, nunca ouvi falar de redefinir funções como gargalo nos aplicativos React. Otimizações prematuras são a raiz de todo mal - preocupe-se com isso quando for um problema

Jeff Cousins
fonte
E a funcionalidade que não está mantendo o estado, mas está fortemente acoplada ao componente, por exemplo, determina algum atributo dinâmico para a renderização.
Dennis
Este é o melhor artigo sobre a diferença entre os dois tipos de componentes em Reagir: code.tutsplus.com/tutorials/...
Arian Acosta
5
A partir do React 16.8, você pode usar o estado em um componente funcional, através do useStategancho.
Greg
A partir do React 16.8, você pode fazer quase tudo nos componentes funcionais, e todos os efeitos podem finalmente ser modularizados com apenas um impacto mínimo no desempenho.
polkovnikov.ph
1
Onde você encontrou a informação onde Facebook officially recommends using functional components wherever possible?
johannchopin 27/03
40

Sempre tente usar funções sem estado (componentes funcionais) sempre que possível. Existem cenários em que você precisará usar uma classe React regular:

  • O componente precisa manter o estado
  • O componente está renderizando demais e você precisa controlá-lo via shouldComponentUpdate
  • Você precisa de um componente de contêiner

ATUALIZAR

Agora existe uma classe React chamada PureComponentque você pode estender (em vez de Component) que implementa a sua própria, shouldComponentUpdateque cuida de comparação de adereços rasos para você. Consulte Mais informação

ffxsam
fonte
43
Always try to use stateless functions (functional components) whenever possible.Eu li dez pessoas dizem isso. Ainda assim, nenhum deles explicou o porquê.
Rotareti 12/07/16
25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.Mais informações: facebook.github.io/react/docs/…
Diogo Cardoso
2
@rotareti Não sei se você acha que recebeu sua pergunta, mas funções puras são muito mais simples de entender, testar e manter. Dados os mesmos parâmetros, eles sempre processam a mesma coisa. Os componentes que mantêm o estado e são alterados quando ocorrem eventos do ciclo de vida são mais difíceis de entender. Para não dizer que às vezes não são necessárias, mas espero que fique claro que, se suas vantagens não forem necessárias, tudo o que eles fazem é adicionar clichê e sobrecarga indesejados sem benefícios.
Door_number_three 18/17
Você também desejará criar uma classe Component se tiver suas próprias definições de manipulador de eventos. Dessa forma, você pode pré-vincular esses manipuladores de eventos ao componente no construtor, em vez de criar uma nova função nova em cada renderização. Observe que isso não é necessário se todos os seus manipuladores de eventos vierem de adereços.
Dobes Vandermeer
Observe que a recomendação do Facebook citada não existe mais (veja meu comentário acima).
Garrett
34

ATUALIZAÇÃO março 2019

https://overreacted.io/how-are-function-components-different-from-classes/

ATUALIZAÇÃO fevereiro de 2019:

Com a introdução dos ganchos do React , parece que as equipes do React desejam que usemos componentes funcionais sempre que possível (o que segue melhor a natureza funcional do JavaScript).

A motivação deles:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

Um componente funcional com ganchos pode fazer quase tudo o que um componente de classe pode fazer, sem nenhuma das desvantagens mencionadas acima.

Eu recomendo usá-los assim que puder.

Resposta original

Os componentes funcionais não são mais leves que os componentes baseados em classes ", eles executam exatamente como classes". - https://github.com/facebook/react/issues/5677#issuecomment-241190513

O link acima é um pouco datado, mas a documentação do React 16.7.0 diz que os componentes funcionais e de classe:

"são equivalentes do ponto de vista do React." - https://reactjs.org/docs/components-and-props.html#stateless-functions

Não há essencialmente nenhuma diferença entre um componente funcional e um componente de classe que apenas implementa o método render, além da sintaxe.

No futuro (citando o link acima) "nós [Reagimos] poderemos adicionar essas otimizações".

Se você está tentando melhorar o desempenho eliminando renderizações desnecessárias, ambas as abordagens fornecem suporte. memopara componentes funcionais e PureComponentpara classes.

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

É realmente com você. Se você quiser menos clichê, vá funcional. Se você gosta de programação funcional e não gosta de aulas, vá funcional. Se você deseja consistência entre todos os componentes da sua base de código, vá com as classes. Se você está cansado de refatorar componentes funcionais para componentes baseados em classe quando precisar de algo como state, vá com as classes.

Galupuf
fonte
1
Acho que tornar cada componente estendido React.Component torna o código mais legível, especialmente para as novas pessoas. É bom quando você vê um componente criado da mesma maneira todas as vezes. Como o @Galupuf disse, os componentes simples têm apenas um método chamado "render ()". Também é bom fazer com que tudo estenda o React.Component porque, quando você deseja começar a vincular "this", ter estado, etc., não precisa refatorar tudo, basta adicionar o que precisa.
jeffski13
10

A partir do React 16.8, o termo Componentes Funcionais sem Estado é enganoso e deve ser evitado, pois não é mais sem estado ( React.SFC reprovado , Dan Abramov no React.SFC ), eles podem ter um estado, podem ter ganchos (que agem como métodos de ciclo de vida), eles se sobrepõem mais ou menos aos componentes da classe

Componentes baseados em classe

Componentes funcionais:

Por que eu prefiro componentes funcionais

  • Reagir fornecer o gancho useEffect que é uma forma muito clara e concisa para combinar o componentDidMount, componentDidUpdatee componentWillUnmountmétodos de ciclo de vida
  • Com ganchos, você pode extrair lógicas que podem ser facilmente compartilhadas entre componentes e testáveis
  • menos confusão sobre o escopo

Reaja a motivação sobre o porquê de usar ganchos (ou seja, componentes funcionais).

Karim
fonte