A principal diferença, a meu ver, é que um componente é renderizado novamente toda vez que seu pai é renderizado novamente, independentemente de os props e o estado do componente terem sido alterados.
Um componente puro, por outro lado, não será renderizado novamente se seus pais forem renderizados novamente, a menos que os props (ou estado) do componente puro tenham sido alterados.
Por exemplo, digamos que temos uma árvore de componentes com uma hierarquia de três níveis: pai, filhos e netos.
Quando os adereços dos pais são alterados de uma maneira que os adereços de apenas um filho são alterados, então:
- se todos os componentes forem componentes regulares, toda a árvore de componentes será renderizada novamente
- se todos os filhos e netos são componentes puros, apenas um filho será renderizado novamente, e um ou todos os seus netos, dependendo se seus objetos foram alterados. Se houver muitos componentes nessa árvore de componentes, isso pode significar um aumento significativo no desempenho.
Às vezes, no entanto, o uso de componentes puros não terá nenhum impacto. Tive um caso desse tipo em que os pais receberam seus acessórios de uma loja redux e precisaram realizar um cálculo complexo dos acessórios de seus filhos. O pai usou uma lista plana para renderizar seus filhos.
O resultado foi que sempre que houve uma pequena alteração no repositório redux, toda a matriz plana dos dados das crianças foi recalculada. Isso significava que, para cada componente da árvore, os objetos eram novos objetos, mesmo que os valores não mudassem.
Nesse caso, os componentes puros não ajudam, e o aumento de desempenho pode ser alcançado apenas usando componentes regulares e verificando os filhos, em shouldComponentUpdate, se for necessário um novo renderizador.