Como você decide, como escolhe entre esses três com base no propósito / tamanho / adereços / comportamento de nossos componentes?
Estender de React.PureComponent
ou para React.Component
um shouldComponentUpdate
método personalizado tem implicações no desempenho. O uso de componentes funcionais sem estado é uma opção "arquitetural" e ainda não possui benefícios de desempenho prontos para uso.
Para componentes simples, apenas para apresentação, que precisam ser reutilizados com facilidade, prefira componentes funcionais sem estado. Dessa forma, você tem certeza de que eles são dissociados da lógica real do aplicativo, que são fáceis de testar e que não têm efeitos colaterais inesperados. A exceção é se, por algum motivo, você tiver muitos deles ou se realmente precisar otimizar o método de renderização (como não é possível definir shouldComponentUpdate
um componente funcional sem estado).
Estenda PureComponent
se você souber que sua saída depende de props / state simples ("simples" significa que não há estruturas de dados aninhadas, pois o PureComponent realiza uma comparação superficial) E você precisa / pode obter algumas melhorias de desempenho.
Estenda Component
e implemente você mesmo shouldComponentUpdate
se precisar de alguns ganhos de desempenho, executando uma lógica de comparação personalizada entre adereços próximos / atuais e estado. Por exemplo, você pode executar rapidamente uma comparação profunda usando lodash # isEqual:
class MyComponent extends Component {
shouldComponentUpdate (nextProps, nextState) {
return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
}
}
Além disso, implementar otimizações próprias shouldComponentUpdate
ou ampliadas PureComponent
são otimizações e, como de costume, você deve começar a investigar isso apenas se tiver problemas de desempenho ( evite otimizações prematuras ). Como regra geral, eu sempre tento fazer essas otimizações depois que o aplicativo está em um estado funcional, com a maioria dos recursos já implementados. É muito mais fácil focar nos problemas de desempenho quando eles realmente atrapalham.
Mais detalhes
Componentes apátridas funcionais:
Estes são definidos apenas usando uma função. Como não há estado interno para um componente sem estado, a saída (que é renderizada) depende apenas dos objetos fornecidos como entrada para esta função.
Prós:
A maneira mais simples possível de definir um componente no React. Se você não precisa gerenciar nenhum estado, por que se preocupar com classes e herança? Uma das principais diferenças entre uma função e uma classe é que, com a função, você tem certeza de que a saída depende apenas da entrada (não do histórico das execuções anteriores).
Idealmente, no seu aplicativo, você deve ter o maior número possível de componentes sem estado, porque isso normalmente significa que você moveu sua lógica para fora da camada de visualização e a moveu para algo como redux, o que significa que você pode testar sua lógica real sem precisar renderizar nada (muito mais fácil de testar, mais reutilizável etc.).
Contras:
Nenhum método de ciclo de vida. Você não tem como definir componentDidMount
e outros amigos. Normalmente, você faz isso em um componente pai mais alto na hierarquia para poder transformar todos os filhos em sem estado.
Não há como controlar manualmente quando uma nova renderização é necessária, pois você não pode definir shouldComponentUpdate
. Uma nova renderização acontece toda vez que o componente recebe novos adereços (nenhuma maneira de comparação superficial etc.). No futuro, o React poderá otimizar automaticamente os componentes sem estado, por enquanto existem algumas bibliotecas que você pode usar. Como componentes sem estado são apenas funções, basicamente é o problema clássico da "memorização de funções".
Não há suporte para referências: https://github.com/facebook/react/issues/4936
Um componente que estende a classe PureComponent VS Um componente normal que estende a classe Component:
Reagir costumava ter um que PureRenderMixin
você poderia anexar a uma classe definida usando React.createClass
sintaxe. O mixin simplesmente definiria uma shouldComponentUpdate
comparação superficial entre os próximos objetos e o próximo estado para verificar se alguma coisa mudou. Se nada mudar, não será necessário executar uma nova renderização.
Se você deseja usar a sintaxe ES6, não pode usar mixins. Portanto, por conveniência, o React introduziu uma PureComponent
classe da qual você pode herdar em vez de usar Component
. PureComponent
apenas implementa shouldComponentUpdate
da mesma maneira que o PureRendererMixin
. É principalmente uma questão de conveniência, para que você não precise implementá-lo por conta própria, pois uma comparação superficial entre o estado atual / próximo e os adereços é provavelmente o cenário mais comum que pode oferecer ganhos rápidos de desempenho.
Exemplo:
class UserAvatar extends Component {
render() {
return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
}
}
Como você pode ver, a saída depende de props.imageUrl
e props.username
. Se em um componente pai você renderizar <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" />
com os mesmos adereços, o React chamariarender
toda vez, mesmo que a saída seja exatamente a mesma. Lembre-se, no entanto, que o React implementa o dom diffing, para que o DOM não seja realmente atualizado. Ainda assim, executar o dom diffing pode ser caro, portanto, nesse cenário, seria um desperdício.
Se o UserAvatar
componente se estender PureComponent
, é realizada uma comparação superficial. E como props e nextProps são os mesmos, render
não serão chamados.
Notas sobre a definição de "puro" no React:
Em geral, uma "função pura" é uma função que avalia sempre o mesmo resultado, com a mesma entrada. A saída (para React, é o que é retornado pelo render
método) não depende de nenhum histórico / estado e não possui efeitos colaterais (operações que alteram o "mundo" fora da função).
No React, os componentes sem estado não são necessariamente componentes puros de acordo com a definição acima, se você chamar "sem estado" um componente que nunca chama this.setState
e que não usa this.state
.
De fato, em a PureComponent
, você ainda pode executar efeitos colaterais durante os métodos do ciclo de vida. Por exemplo, você pode enviar uma solicitação ajax para dentro componentDidMount
ou executar algum cálculo do DOM para ajustar dinamicamente a altura de uma div dentro render
.
A definição de "componentes mudos" tem um significado mais "prático" (pelo menos no meu entendimento): um componente idiota "é informado" do que fazer por um componente pai por meio de adereços e não sabe como fazer as coisas, mas usa adereços retornos de chamada.
Exemplo de um "inteligente" AvatarComponent
:
class AvatarComponent extends Component {
expandAvatar () {
this.setState({ loading: true });
sendAjaxRequest(...).then(() => {
this.setState({ loading: false });
});
}
render () {
<div onClick={this.expandAvatar}>
<img src={this.props.username} />
</div>
}
}
Exemplo de um "burro" AvatarComponent
:
class AvatarComponent extends Component {
render () {
<div onClick={this.props.onExpandAvatar}>
{this.props.loading && <div className="spinner" />}
<img src={this.props.username} />
</div>
}
}
No final, eu diria que "burro", "sem estado" e "puro" são conceitos bem diferentes que às vezes podem se sobrepor, mas não necessariamente, dependendo principalmente do seu caso de uso.
props
. exemplo .PureComponent
, você não deve implementarshouldComponentUpdate()
. Você deve receber um aviso se fizer isso realmente.PureComponent
componentes que possuem propriedades de objeto / matriz aninhadas. Claro que você precisa estar ciente do que está acontecendo. Se eu entendi corretamente, se você não está alterando props / state diretamente (que o React tenta impedir que você faça com avisos) ou por meio de uma biblioteca externa, você deve usar bem, emPureComponent
vez deComponent
praticamente todo lugar ... com a exceção de componentes muito simples em que ele pode realmente ser mais rápido não usá-lo - veja news.ycombinator.com/item?id=14418576Eu não sou um gênio sobre reagir, mas pelo meu entendimento, podemos usar cada componente nas seguintes situações
Componente sem estado - esse é o componente que não possui ciclo de vida; portanto, esses componentes devem ser usados na renderização do elemento repetido do componente pai, como na renderização da lista de texto que apenas exibe as informações e não possui nenhuma ação a ser executada.
Componente puro - esses são os itens que possuem ciclo de vida e sempre retornam o mesmo resultado quando um conjunto específico de adereços é fornecido. Esses componentes podem ser usados ao exibir uma lista de resultados ou dados de objetos específicos que não possuem elementos filhos complexos e usados para executar operações que impactam apenas a si mesmas. essa lista de cartões de usuário ou de produtos (informações básicas do produto) e a única ação que o usuário pode executar é clicar para exibir a página de detalhes ou adicionar ao carrinho.
Componentes normais ou componentes complexos - usei o termo componente complexo porque esses geralmente são os componentes no nível da página e consistem em muitos componentes filhos e, já que cada filho pode se comportar de maneira única e única, para que você não tenha 100% de certeza de que renderize o mesmo resultado em um determinado estado. Como eu disse, geralmente estes devem ser usados como componentes de contêineres
fonte
PureComponent
de componentes e componentes no nível raiz perto do topo da sua hierarquia geralmente é onde você verá os maiores ganhos de desempenho. É claro que você precisa evitar a mutação de objetos e declarar diretamente que componentes puros funcionem corretamente, mas a mutação direta de objetos é um antipadrão no React de qualquer maneira.React.Component
é o componente "normal" padrão. Você os declara usando aclass
palavra-chave eextends React.Component
. Pense neles como uma classe, com métodos de ciclos de vida, manipuladores de eventos e quaisquer outros métodos.React.PureComponent
é umReact.Component
que implementashouldComponentUpdate()
com uma função que faz uma comparação superficial de seusprops
estate
. Você deve usarforceUpdate()
se souber que o componente possui adereços ou dados aninhados de estado que foram alterados e deseja renderizar novamente. Portanto, eles não são ótimos se você precisar de componentes para renderizar novamente quando matrizes ou objetos que você passar como adereços ou definir sua alteração de estado.Componentes funcionais são aqueles que não têm funções de ciclo de vida. Eles são supostamente apátridas, mas são tão legais e limpos que agora temos ganchos (desde o React 16.8) para que você ainda possa ter um estado. Então eu acho que eles são apenas "componentes limpos".
fonte