React components composition: como acertar isso

dougsource

doug-source

Posted on July 18, 2024

React components composition: como acertar isso

Nota: apenas traduzi o texto abaixo e postei aqui. Atualizei um pouco apenas os códigos. As referências estão no fim deste artigo.

Publicado originalmente em https://www.developerway.com. O site tem mais artigos como este. 😉

Uma das coisas mais interessantes e desafiadoras no React é não dominar algumas técnicas avançadas de gerenciamento de state ou como usar o Context de maneira adequada. Mais complicado de acertar é como e quando devemos separar nosso código em components independentes e como compô-los adequadamente. Muitas vezes vejo desenvolvedores caindo em duas armadilhas: ou eles não extraem eles rápido o suficiente e acabam com enormes "monólitos" de components que fazem muitas coisas ao mesmo tempo e que são um pesadelo para manter. Ou, especialmente depois de terem sido queimados algumas vezes pelo pattern anterior, eles extraem components muito cedo, o que resulta em uma combinação complicada de múltiplas abstrações, código com engenharia excessiva e, novamente, um pesadelo para manter.

O que quero fazer hoje é oferecer algumas técnicas e regras que possam ajudar a identificar quando e como extrair components no prazo e como não cair na armadilha do excesso de engenharia. Mas primeiro, vamos atualizar alguns princípios básicos: o que é composition (composição) e quais composition patterns estão disponíveis para nós?

React components composition patterns

Components simples

Components simples são um bloco de construção básico do React. Eles podem aceitar props, ter algum state e podem ser bastante complicados, apesar do nome. Um Button component que aceita properties title e onClick e renderiza uma button tag é um component simples.

import { ComponentPropsWithoutRef, ReactNode } from 'react';

type ButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'title'> & {
    title: ReactNode
};

const Button = ({ title, onClick }: ButtonProps) => (
    <button onClick={onClick}>{title}</button>
);
Enter fullscreen mode Exit fullscreen mode

Qualquer component pode renderizar outros components – isso é composition. Um Navigation component que renderiza esse Button - também um component simples, que compõe outros components:

// onClickHandler declarado aqui

const Navigation = () => (
    <>
          {/** Renderizando o Button component no Navigation component. **/}
          {/** Composition! **/}
          <Button title="Create" onClick={onClickHandler} />
          {/** ... algum outro código de navigation **/}
    </>
);
Enter fullscreen mode Exit fullscreen mode

Com esses components e sua composition, podemos implementar UI tão complicada quanto quisermos. Tecnicamente, nem precisamos de outros patterns e técnicas, todos eles são apenas úteis que apenas melhoram a reutilização de código ou resolvem apenas casos de uso específicos.

Container components

Container components é uma técnica de composition mais avançada. A única diferença dos components simples é que eles, entre outras props, permitem passar a prop especial children, para os quais o React possui sua própria sintaxe. Se nosso Button do exemplo anterior aceitasse não o title, mas children, seria escrito assim:

// o código é exatamente o mesmo! basta substituir "title" por "children"

import { ComponentPropsWithoutRef } from 'react';

type ButtonProps = ComponentPropsWithoutRef<'button'>;

const Button = ({ children, onClick }: ButtonProps) => (
    <button onClick={onClick}>{children}</button>
);
Enter fullscreen mode Exit fullscreen mode

O que não é diferente do title na perspectiva do Button. A diferença está no lado do "consumer", a sintaxe children é especial e se parece com suas tags HTML normais:

// onClickHandler declarado aqui

const Navigation = () => {
    return (
        <>
            <Button onClick={onClickHandler}>Create</Button>
            {/** ... algum outro código de navigation **/}
        </>
    );
};
Enter fullscreen mode Exit fullscreen mode

Qualquer coisa pode entrar em children. Podemos, por exemplo, adicionar um Icon component além do texto, e então Navigation terá uma composition de components Button e Icon:

// onClickHandler declarado aqui

const Navigation = () => (
    <>
        <Button onClick={onClickHandler}>
            {/** Icon component é renderizado dentro de button, **/}
            {/** mas button não sabe **/}
            <Icon />
            <span>Create</span>
        </Button>
        {/** ... algum outro código de navigation **/}
   </>
);
Enter fullscreen mode Exit fullscreen mode

Navigation controla o que acontece com children; da perspectiva de Button, ela apenas renderiza tudo o que o "consumer" deseja.

Veremos mais exemplos práticos dessa técnica mais adiante neste artigo.

Existem outros composition patterns, como higher-order components, passando components como props ou context, mas esses devem ser usados ​​apenas para casos de uso muito específicos. Components simples e container components são os dois principais pilares do desenvolvimento do React, e é melhor aperfeiçoar o uso deles antes de tentar introduzir técnicas mais avançadas.

Agora que você os conhece, está pronto para implementar a UI mais complicada que precisar!

Ok, estou brincando, não vou fazer um artigo do tipo "como desenhar uma coruja" aqui. 😅

how to draw an owl

É hora de algumas regras e diretrizes para que possamos realmente desenhar aquela coruja e construir React apps complicados com facilidade.

Quando é um bom momento para extrair components?

As principais regras de desenvolvimento e decomposition do React que gosto de seguir, e quanto mais codifico, mais fortemente me sinto a respeito delas, são:

  • sempre comece a implementação do topo
  • extrair components somente quando houver uma necessidade real
  • sempre comece com components "simples", introduza outras técnicas de composition somente quando houver real necessidade delas

Qualquer tentativa de pensar "com antecedência" ou começar "de baixo para cima" a partir de pequenos components reutilizáveis ​​sempre termina em APIs de components excessivamente complicadas ou em components que carecem de metade da funcionalidade necessária.

E a primeira regra para quando um component precisa ser decomposto em components menores é quando um component é muito grande. Um bom tamanho para um component para mim é quando ele cabe inteiramente na tela do meu laptop. Se eu precisar realizar scroll para ler o código do component, é um sinal claro de que ele é muito grande.

Vamos começar a codificar agora, para ver como isso funciona na prática. Vamos implementar uma página Jira típica do zero hoje, nada menos (bem, mais ou menos, pelo menos vamos começar 😅).

jira page

Esta é a tela de uma página de edição do meu projeto pessoal onde guardo minhas receitas favoritas encontradas online 🍣. Lá precisamos implementar, como você pode ver:

  • top bar (barra superior) com logo, alguns menus, button "create" e search bar (barra de pesquisa)
  • sidebar (barra lateral) à esquerda, com o nome do projeto, seções collapsable de "planejamento" e "desenvolvimento" com itens dentro (também divididos em grupos), com uma seção sem nome com menu items abaixo
  • uma grande seção de "conteúdo da página", onde são mostradas todas as informações sobre o issue atual

Então, vamos começar a codificar tudo isso em apenas um grande component. Provavelmente será algo assim:

export const JiraIssuePage = () => (
    <div className="app">
        <div className="top-bar">
            <div className="logo">logo</div>
            <ul className="main-menu">
                <li>
                    <a href="#">Your work</a>
                </li>
                <li>
                    <a href="#">Projects</a>
                </li>
                <li>
                    <a href="#">Filters</a>
                </li>
                <li>
                    <a href="#">Dashboards</a>
                </li>
                <li>
                    <a href="#">People</a>
                </li>
                <li>
                    <a href="#">Apps</a>
                </li>
            </ul>
            <button className="create-button">Create</button>
            {/** mais top bar items aqui, como **/}
            {/** SearchBar e ProfileMenu **/}
        </div>
        <div className="main-content">
            <div className="sidebar">
                <div className="sidebar-header">ELS project</div>
                <div className="sidebar-section">
                    <div
                        className="sidebar-section-title"
                    >Planning</div>
                    <button className="board-picker">ELS board</button>
                    <ul className="section-menu">
                        <li>
                            <a href="#">Roadmap</a>
                        </li>
                        <li>
                            <a href="#">Backlog</a>
                        </li>
                        <li>
                            <a href="#">Kanban board</a>
                        </li>
                        <li>
                            <a href="#">Reports</a>
                        </li>
                        <li>
                            <a href="#">Roadmap</a>
                        </li>
                    </ul>

                    <ul className="section-menu">
                        <li>
                            <a href="#">Issues</a>
                        </li>
                        <li>
                            <a href="#">Components</a>
                        </li>
                    </ul>
                </div>
                <div className="sidebar-section">
                    sidebar development section
                </div>
                {/** outras sections **/}
            </div>
            <div className="page-content">
                {/** ... aqui haverá muito código **/
                {/** para visualização da issue **/}
            </div>
        </div>
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Agora, não implementei nem metade dos itens necessários lá, sem falar na lógica, e o component já é grande demais para ser lido de uma só vez. Veja em codesandbox. Isso é bom e esperado! Portanto, antes de prosseguir, é hora de dividi-lo em partes mais gerenciáveis.

A única coisa que preciso fazer é criar alguns novos components e copiar e colar o código neles. Não tenho nenhum caso de uso para nenhuma das técnicas avançadas (ainda), então tudo será um component simples.

Vou criar um Topbar component, que terá tudo relacionado à top bar, um Sidebar component, para tudo relacionado à sidebar, como você pode imaginar, e um Issue component para a parte principal que não iremos abordar hoje. Dessa forma, nosso component principal JiraIssuePage fica com este código:

export const JiraIssuePage = () => (
    <div className="app">
        <Topbar />
        <div className="main-content">
            <Sidebar />
            <div className="page-content">
                <Issue />
            </div>
        </div>
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Agora vamos dar uma olhada na implementação do novo Topbar component:

export const Topbar = () => (
    <div className="top-bar">
        <div className="logo">logo</div>
        <ul className="main-menu">
            <li>
                <a href="#">Your work</a>
            </li>
            <li>
                <a href="#">Projects</a>
            </li>
            <li>
                <a href="#">Filters</a>
            </li>
            <li>
                <a href="#">Dashboards</a>
            </li>
            <li>
                <a href="#">People</a>
            </li>
            <li>
                <a href="#">Apps</a>
            </li>
        </ul>
        <button className="create-button">Create</button>
        {/** mais top bar items aqui, como **/}
        {/** SearchBar e ProfileMenu **/}
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Se eu implementasse todos os itens lá (searchbar, todos os submenus, icons à direita), esse component também seria muito grande, então também precisa ser dividido. E este é sem dúvida um caso mais interessante que o anterior. Porque, tecnicamente, posso simplesmente extrair o MainMenu component dele para torná-lo pequeno o suficiente.

export const Topbar = () => (
    <div className="top-bar">
        <div className="logo">logo</div>
        <MainMenu />
        <button className="create-button">Create</button>
        {/** mais top bar items aqui, como **/}
        {/** SearchBar e ProfileMenu **/}
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Mas extrair apenas MainMenu tornou o Topbar component um pouco mais difícil de ler para mim. Antes, quando eu olhava para Topbar, eu poderia descrevê-lo como "um component que implementa várias coisas no topbar", e focar nos detalhes apenas quando preciso. Agora a descrição seria "um componente que implementa várias coisas na top bar E compõe algum component aleatório do MainMenu". O fluxo de leitura está arruinado.

Isso me leva à minha segunda regra de decomposition de components: ao extrair components menores, não pare no meio do caminho. Um component deve ser descrito como um "component que implementa várias coisas" ou como um "component que compõe vários components juntos”, e não ambos.

Portanto, uma implementação muito melhor do Topbar component seria assim:

export const Topbar = () => (
    <div className="top-bar">
        <Logo />
        <MainMenu />
        <Create />
        {/** mais top bar items aqui, como **/}
        {/** SearchBar e ProfileMenu **/}
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Muito mais fácil de ler agora!

E exatamente a mesma história com o Sidebar component - muito grande se eu tivesse implementado todos os itens, então preciso dividi-lo:

export const Sidebar = () => (
    <div className="sidebar">
        <Header />
        <PlanningSection />
        <DevelopmentSection />
        {/** outras sidebar sections **/}
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Veja o exemplo completo na caixa de códigos.

E então basta repetir essas etapas sempre que um componente ficar muito grande. Em teoria, podemos implementar toda esta página do Jira usando nada mais do que componentes simples.

Quando é a hora de apresentar os Container components?

Agora a parte divertida: vamos ver quando devemos apresentar algumas técnicas avançadas e por quê. Começando com Container components.

Primeiro, vamos dar uma olhada no design novamente. Mais especificamente - nas seções Planning e Development no sidebar menu.

planning and development

Eles não apenas compartilham o mesmo design do title, mas também o mesmo comportamento: clicar no title recolhe a seção e, no modo "collapsed", o ícone de minisseta aparece. E nós o implementamos como dois components diferentes - PlanningSection e DevelopmentSection. Eu poderia, é claro, apenas implementar a lógica de "collapse" em ambos, afinal é apenas uma questão de state simples:

import { useState } from 'react';

const PlanningSection = () => {
    const [isCollapsed, setIsCollapsed] = useState(false);
    return (
        <div className="sidebar-section">
            <div
                onClick={() => setIsCollapsed(!isCollapsed)}
                className="sidebar-section-title"
            >
                Planning
            </div>

            {!isCollapsed && <>...todo o resto do código</>}
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

Mas:

  • há muita repetição mesmo entre esses dois componentes
  • o conteúdo dessas seções é realmente diferente para cada tipo de projeto ou tipo de página, portanto, ainda mais repetição no futuro próximo

Idealmente, quero encapsular a lógica do comportamento collapsed/expanded e o design do title, deixando diferentes seções com controle total sobre os itens que estão dentro. Este é um caso de uso perfeito para os Container components. Posso simplesmente extrair tudo do exemplo de código acima em um component e passar menu items como children. Teremos um CollapsableSection component:

import { ReactNode, useState } from 'react';

type CollapsableSectionProps = {
    children: ReactNode;
    title: ReactNode;
};

const CollapsableSection = ({
    children,
    title
}: CollapsableSectionProps) => {
    const [isCollapsed, setIsCollapsed] = useState(false);

    return (
        <div className="sidebar-section">
            <div
                className="sidebar-section-title"
                onClick={() => setIsCollapsed(!isCollapsed)}
            >
                {title}
            </div>

            {!isCollapsed && <>{children}</>}
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

e PlanningSection (e DevelopmentSection e todas as outras seções futuras) se tornarão apenas isto:

// import de CollapsableSection

const PlanningSection = () => (
    <CollapsableSection title="Planning">
        <button className="board-picker">ELS board</button>

        <ul className="section-menu">... todos os menu items aqui</ul>
    </CollapsableSection>
);
Enter fullscreen mode Exit fullscreen mode

Uma história muito semelhante acontecerá com nosso root component JiraIssuePage. No momento está assim:

// todos os imports dos components aqui

export const JiraIssuePage = () => (
    <div className="app">
        <Topbar />
        <div className="main-content">
            <Sidebar />
            <div className="page-content">
                <Issue />
            </div>
        </div>
    </div>
);
Enter fullscreen mode Exit fullscreen mode

Mas assim que começarmos a implementar outras páginas acessíveis a partir da sidebar, veremos que todas sigam exatamente o mesmo pattern - sidebar e topbar permanecem as mesmas, e apenas a área "conteúdo da página" muda. Graças ao trabalho de decomposition que fizemos antes, podemos simplesmente copiar e colar esse layout em cada página - afinal, não é tanto código. Mas como todos são exatamente iguais, seria bom apenas extrair o código que implementa todas as partes comuns e deixar apenas os components que mudam para as páginas específicas. Mais uma vez, um caso perfeito para o "container" component:

import { ReactNode } from 'react';

type JiraPageLayoutProps = {
    children: ReactNode;
};

const JiraPageLayout = ({ children }: JiraPageLayoutProps) => (
    <div className="app">
        <Topbar />
        <div className="main-content">
            <Sidebar />
            <div className="page-content">{children}</div>
        </div>
    </div>
);
Enter fullscreen mode Exit fullscreen mode

E nosso JiraIssuePage (e futuros JiraProjectPage, JiraComponentsPage, etc, todas as futuras páginas acessíveis na sidebar) se torna apenas isto:

export const JiraIssuePage = () => (
    <JiraPageLayout>
        <Issue />
    </JiraPageLayout>
);
Enter fullscreen mode Exit fullscreen mode

Se eu quisesse resumir a regra em apenas uma frase, poderia ser esta: extrair Container components quando houver necessidade de compartilhar alguma lógica visual ou comportamental que encapsule elements que ainda precisam estar sob controle do "consumer".

Container Components – caso de uso de desempenho

Outro caso de uso muito importante para Container components é melhorar o desempenho dos components. Tecnicamente a performance foge um pouco do assunto para a conversa sobre composition, mas seria um crime não mencioná-la aqui.

No Jira real, o Sidebar component pode ser draggable - você pode resize ele fazendo o dragging dele para a esquerda e para a direita pela borda. Como implementaríamos algo assim? Provavelmente introduziríamos um Handle component, algum state para a width da sidebar e então faríamos o listen do "mousemove" event. Uma implementação rudimentar seria mais ou menos assim:

// import do Handle component
import { useState, useRef, useEffect } from 'react';

export const Sidebar = () => {
    const [width, setWidth] = useState(240);
    const [startMoving, setStartMoving] = useState(false);
    const ref = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (!ref.current) return;
        const changeWidth = (e: MouseEvent) => {
            if (!startMoving) return;
            if (!ref.current) return;

            const left = ref.current.getBoundingClientRect().left;
            const wi = e.clientX - left;

            setWidth(wi);
        };

        ref.current.addEventListener('mousemove', changeWidth);

        return () => ref.current?.removeEventListener('mousemove', changeWidth);
    }, [startMoving, ref]);

    const onStartMoving = () => {
        setStartMoving(true);
    };

    const onEndMoving = () => {
        setStartMoving(false);
    };

    return (
        <div
            className="sidebar"
            ref={ref}
            onMouseLeave={onEndMoving}
            style={{ width: `${width}px` }}
        >
            <Handle onMouseDown={onStartMoving} onMouseUp={onEndMoving} />
            {/* ... o resto do código */}
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

Há, no entanto, um problema aqui: cada vez que movemos o mouse, iremos disparar uma atualização de state, que por sua vez acionará a nova renderização de todo o Sidebar component. Embora em nossa sidebar rudimentar não seja perceptível, isso pode tornar o "dragging" visivelmente lento quando o component se torna mais complicado. Container components são uma solução perfeita para isso: tudo o que precisamos é extrair todas as operações pesadas de state em um Container component e passar todo o resto pelos children.

import { ReactNode } from 'react';

type DraggableSidebarProps = { children: ReactNode };

const DraggableSidebar = ({ children }: DraggableSidebarProps) => {
    // todo o código de gestão do estado como antes
    return (
        <div
            className="sidebar"
            ref={ref}
            onMouseLeave={onEndMoving}
            style={{ width: `${width}px` }}
        >
            <Handle onMouseDown={onStartMoving} onMouseUp={onEndMoving} />
            {/** children não seré afetado pelos **/}
            {/** re-renders deste component **/}
            {children}
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

E nosso Sidebar component se transformará nisso:

// todos os imports dos components

export const Sidebar = () => (
    <DraggableSidebar>
        <Header />
        <PlanningSection />
        <DevelopmentSection />
        {/* outras seções */}
    </DraggableSidebar>
);
Enter fullscreen mode Exit fullscreen mode

Dessa forma, o DraggableSidebar component ainda será renderizado novamente a cada mudança de state, mas será muito barato, pois é apenas uma div. E tudo o que chega em children não será afetado pelas atualizações de state deste component.

Veja todos os exemplos de container components neste codesandbox. E para comparar o caso de uso de re-renders ruims, consulte este codesandbox. Preste atenção ao console output enquanto realiza o dragging do sidebar nesses exemplos - o PlanningSection component loga constantemente na implementação "ruim" e apenas uma vez na implementação "boa".

E se você quiser saber mais sobre vários patterns e como eles influenciam o desempenho do React, você pode achar esses artigos interessantes: Como escrever código React de alto desempenho: regras, patterns, o que fazer e o que não fazer, Por que custom react hooks podem destruir o desempenho do seu app, Como escrever React apps de alto desempenho com Context

Este state pertence a este component?

Outra coisa, além do tamanho, que pode sinalizar que um component deve ser extraído, é o gerenciamento de state. Ou, para ser mais preciso, gerenciamento de state que é irrelevante para a funcionalidade do component. Deixe-me mostrar o que quero dizer.

Um dos itens da sidebar no Jira real é o item "Add shortcut", que abre um modal dialog quando você clica nele. Como você implementaria isso em nosso app? O modal dialog em si obviamente será seu próprio component, mas onde você introduziria o state que abre ele? Algo assim?

// import do ModalDialog component
import { useState } from 'react';

const SomeSection = () => {
    const [showAddShortcuts, setShowAddShortcuts] = useState(false);

    return (
        <div className="sidebar-section">
            <ul className="section-menu">
                <li>
                    <span onClick={() => setShowAddShortcuts(true)}>
                        Add shortcuts
                    </span>
                </li>
            </ul>
            {showAddShortcuts && (
                <ModalDialog onClose={() => setShowAddShortcuts(false)} />
            )}
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

Você pode ver algo assim em todos os lugares e não há nada de criminoso nesta implementação. Mas se eu estivesse implementando e quisesse tornar esse component perfeito do ponto de vista da composition, extrairia esse state e os components relacionados a ele externamente. E a razão é simples: esse state não tem nada a ver com o SomeSection component. Este state controla um modal dialog que aparece quando você clica no shortcuts item (de atalhos). Isso torna a leitura deste component um pouco mais difícil para mim - vejo um component que é "section" e a próxima linha é algum state aleatório que não tem nada a ver com "section". Então, em vez da implementação acima, eu extrairia o item e o state que realmente pertence a esse item em seu próprio component:

// import do ModalDialog component
import { useState } from 'react';

const AddShortcutItem = () => {
    const [showAddShortcuts, setShowAddShortcuts] = useState(false);

    return (
        <>
            <span onClick={() => setShowAddShortcuts(true)}>Add shortcuts</span>
            {showAddShortcuts && (
                <ModalDialog onClose={() => setShowAddShortcuts(false)} />
            )}
        </>
    );
};
Enter fullscreen mode Exit fullscreen mode

E o section component se torna muito mais simples como bônus:

// import do AddShortcutItem component

const OtherSection = () => {
    return (
        <div className="sidebar-section">
            <ul className="section-menu">
                <li>
                    <AddShortcutItem />
                </li>
            </ul>
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

Veja ele no codesandbox.

Pela mesma lógica, no Topbar component eu moveria o state futuro que controla os menus para um SomeDropdownMenu component, todos os states relacionados à pesquisa para o Search component e tudo relacionado à abertura do dialog "create issue" para o CreateIssue component.

O que torna um component um "bom component"?

Uma última coisa antes de encerrar por hoje. No resumo quero escrever "o segredo de escrever apps escaláveis ​​em React é extrair bons components no momento certo". Já cobrimos o "momento certo", mas o que exatamente é um "bom component"? Depois de tudo o que abordamos sobre composition até agora, acho que estou pronto para escrever uma definição e algumas regras aqui.

Um "bom component" é aquele que posso ler facilmente e entender o que faz à primeira vista.

Um "bom component" deve ter um bom nome autodescritivo. Sidebar para um component que renderiza sidebar é um bom nome. CreateIssue para um component que lida com a criação de issues é um bom nome. SidebarController para um component que renderiza sidebar items específicos para a página "Issues" não é um bom nome (o nome indica que o component tem algum propósito genérico, não específico para uma página específica).

Um "bom component" não faz coisas que sejam irrelevantes para o seu propósito declarado. O Topbar component que renderiza apenas itens na top bar e controla apenas o comportamento da topbar é um bom component. O Sidebar component, que controla o state de várias modal dialogs, não é o melhor component.

Fechando bullet points

Agora posso escrever 😄! O segredo de escrever apps escaláveis ​​no React é extrair bons components no momento certo, nada mais.

O que constitui um bom component?

  • tamanho, que permite lê-lo sem scrolling
  • nome, que indica o que faz
  • nenhuma gestão de state irrelevante
  • implementação fácil de ler

Quando é hora de dividir um component em components menores?

  • quando um component é muito grande
  • quando um component executa operações pesadas de gerenciamento de state que podem afetar o desempenho
  • quando um component gerencia um state irrelevante

Quais são as regras gerais de composition dos components?

  • sempre comece a implementação do topo
  • extraia components somente quando você tiver um caso de uso real para ele, não antecipadamente
  • sempre comece com os components simples, introduza técnicas avançadas somente quando forem realmente necessárias, não com antecedência

Por hoje é isso, espero que tenham gostado da leitura e achado útil!

Até a próxima ✌🏼

...

Publicado originalmente em https://www.developerway.com. O site tem mais artigos como este. 😉

Assine a newsletter, conecte-se no LinkedIn ou siga no Twitter para ser notificado assim que o próximo artigo for publicado.

Fonte

Artigo escrito por Nadia Makarevich.

💖 💪 🙅 🚩
dougsource
doug-source

Posted on July 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related