v19.2Latest

Compartilhando Estado Entre Componentes

Às vezes, você quer que o estado de dois componentes mude sempre juntos. Para fazer isso, remova o estado de ambos, mova-o para o pai comum mais próximo e, em seguida, passe-o para eles via props. Isso é conhecido comoelevar o estado,e é uma das coisas mais comuns que você fará ao escrever código React.

Você aprenderá
  • Como compartilhar estado entre componentes elevando-o
  • O que são componentes controlados e não controlados

Elevando o estado com um exemplo

Neste exemplo, um componente paiAccordionrenderiza doisPanels separados:

  • Accordion
    • Panel
    • Panel

Cada componentePaneltem um estado booleanoisActiveque determina se seu conteúdo está visível.

Pressione o botão Mostrar para ambos os painéis:

Observe como pressionar o botão de um painel não afeta o outro painel—eles são independentes.

Diagrama mostrando uma árvore de três componentes, um pai rotulado Accordion e dois filhos rotulados Panel. Ambos os componentes Panel contêm isActive com valor false.Diagrama mostrando uma árvore de três componentes, um pai rotulado Accordion e dois filhos rotulados Panel. Ambos os componentes Panel contêm isActive com valor false.

Inicialmente, o estadoisActivede cadaPanel é false, então ambos aparecem recolhidos

O mesmo diagrama do anterior, com o isActive do primeiro componente filho Panel destacado indicando um clique com o valor isActive definido como true. O segundo componente Panel ainda contém o valor false.O mesmo diagrama do anterior, com o isActive do primeiro componente filho Panel destacado indicando um clique com o valor isActive definido como true. O segundo componente Panel ainda contém o valor false.

Clicar no botão de qualquerPanelatualizará apenas o estadoisActivedessePanelespecífico

Mas agora digamos que você queira mudar isso para que apenas um painel esteja expandido por vez.Com esse design, expandir o segundo painel deve recolher o primeiro. Como você faria isso?

Para coordenar esses dois painéis, você precisa "elevar seu estado" para um componente pai em três etapas:

  1. Removao estado dos componentes filhos.
  2. Passedados fixos do pai comum.
  3. Adicioneestado ao pai comum e passe-o para baixo junto com os manipuladores de eventos.

Isso permitirá que o componenteAccordioncoordene ambos osPanels e expanda apenas um por vez.

Etapa 1: Remova o estado dos componentes filhos

Você dará o controle do estadoisActivedoPanelao seu componente pai. Isso significa que o componente pai passaráisActivepara oPanelcomo uma prop. Comeceremovendo esta linhado componentePanel:

E, em vez disso, adicioneisActiveà lista de props doPanel:

Agora o componente pai doPanel pode controlarisActive passando-o como uma prop.Por outro lado, o componentePanel agora não tem controlesobre o valor deisActive—isso agora cabe ao componente pai!

Passo 2: Passe dados fixos do pai comum

Para elevar o estado, você deve localizar o componente pai comum mais próximode ambosos componentes filhos que você deseja coordenar:

  • Accordion(pai comum mais próximo)
    • Panel
    • Panel

Neste exemplo, é o componenteAccordion. Como está acima de ambos os painéis e pode controlar suas props, ele se tornará a "fonte da verdade" sobre qual painel está ativo no momento. Faça o componenteAccordionpassar um valor fixo deisActive(por exemplo,true) para ambos os painéis:

Tente editar os valores fixos deisActiveno componenteAccordione veja o resultado na tela.

Passo 3: Adicione estado ao pai comum

Elevar o estado frequentemente muda a natureza do que você está armazenando como estado.

Neste caso, apenas um painel deve estar ativo por vez. Isso significa que o componente pai comumAccordionprecisa acompanharqualpainel está ativo. Em vez de um valorboolean, ele poderia usar um número como o índice doPanelativo para a variável de estado:

Quando oactiveIndex é 0, o primeiro painel está ativo, e quando é1, é o segundo.

Clicar no botão "Mostrar" em qualquerPanelprecisa alterar o índice ativo noAccordion. UmPanelnão pode definir o estadoactiveIndexdiretamente porque ele é definido dentro doAccordion. O componenteAccordionprecisapermitir explicitamenteque o componentePanelaltere seu estadopassando um manipulador de eventos como uma prop:

O <button>dentro doPanelagora usará a proponShowcomo seu manipulador de evento de clique:

Isso completa a elevação do estado! Mover o estado para o componente pai comum permitiu que você coordenasse os dois painéis. Usar o índice ativo em vez de duas flags "está visível" garantiu que apenas um painel esteja ativo por vez. E passar o manipulador de eventos para o filho permitiu que o filho alterasse o estado do pai.

Diagrama mostrando uma árvore de três componentes: um pai chamado Accordion e dois filhos chamados Panel. Accordion contém um valor activeIndex de zero, que se transforma em um valor isActive de true passado para o primeiro Panel, e um valor isActive de false passado para o segundo Panel.Diagrama mostrando uma árvore de três componentes: um pai chamado Accordion e dois filhos chamados Panel. Accordion contém um valor activeIndex de zero, que se transforma em um valor isActive de true passado para o primeiro Panel, e um valor isActive de false passado para o segundo Panel.

Inicialmente, oAccordiontemactiveIndexigual a0, então o primeiroPanelrecebeisActive = true

O mesmo diagrama do anterior, com o valor activeIndex do componente pai Accordion destacado, indicando um clique com o valor alterado para um. O fluxo para ambos os componentes filhos Panel também está destacado, e o valor isActive passado para cada filho é definido como o oposto: false para o primeiro Panel e true para o segundo.O mesmo diagrama do anterior, com o valor activeIndex do componente pai Accordion destacado, indicando um clique com o valor alterado para um. O fluxo para ambos os componentes filhos Panel também está destacado, e o valor isActive passado para cada filho é definido como o oposto: false para o primeiro Panel e true para o segundo.

Quando o estadoactiveIndexdoAccordionmuda para1, o segundoPanelrecebeisActive = trueem vez disso

Deep Dive
Componentes controlados e não controlados

Uma única fonte da verdade para cada estado

Em uma aplicação React, muitos componentes terão seu próprio estado. Alguns estados podem "viver" próximos aos componentes folha (componentes na parte inferior da árvore), como inputs. Outros estados podem "viver" mais próximos do topo do aplicativo. Por exemplo, até mesmo bibliotecas de roteamento do lado do cliente geralmente são implementadas armazenando a rota atual no estado React e passando-a para baixo por props!

Para cada parte única do estado, você escolherá o componente que o "possui".Este princípio também é conhecido como ter uma"única fonte da verdade".Isso não significa que todo o estado vive em um só lugar — mas que paracadaparte do estado, há um componenteespecíficoque detém essa informação. Em vez de duplicar o estado compartilhado entre componentes,eleve-opara o pai comum compartilhado epasse-o para baixopara os filhos que precisam dele.

Seu aplicativo mudará conforme você trabalha nele. É comum que você mova o estado para baixo ou de volta para cima enquanto ainda está descobrindo onde cada parte do estado "vive". Isso tudo faz parte do processo!

Para ver como isso se sente na prática com mais alguns componentes, leiaPensando em React.

Recapitulação

  • Quando você deseja coordenar dois componentes, mova o estado deles para o pai comum.
  • Em seguida, passe as informações para baixo através de props do pai comum.
  • Por fim, passe os manipuladores de eventos para baixo para que os filhos possam alterar o estado do pai.
  • É útil considerar componentes como "controlados" (dirigidos por props) ou "não controlados" (dirigidos por estado).

Experimente alguns desafios

Challenge 1 of 2:Entradas sincronizadas #

Estas duas entradas são independentes. Faça com que elas permaneçam sincronizadas: editar uma entrada deve atualizar a outra entrada com o mesmo texto, e vice-versa.