Front End

15 ago, 2018

Referenciando componentes no React

Publicidade

Continuando a série de artigos sobre React, na qual eu expliquei com mais detalhes o funcionamento da função setState e mostrei possíveis maneiras utilizarmos essa função. Neste artigo, mostrarei como referenciar componentes através do atributo ref.

Por que referenciar componentes?

Através do atributo ref conseguimos acessar elementos do DOM ou do React criados durante o método render. Com a referência, podemos realizar modificações ou disparar funções de componentes pais para os seus filhos, e até mesmo realizar interações no DOM referente ao componente renderizado.

Observação: evite utilizar o ref para exemplos ou necessidades que podem ser feitas de forma declarativa através dos componentes.

Como referenciar componentes?

Atualmente, se você já trabalhou com React antes, deve se lembrar da String Ref API:

<MeuBotao ref="meuBotao"/>

Dessa maneira, estamos atribuindo uma nova propriedade para nossa classe chamada meuBotao. Podemos acessá-la dentro de outras funções através de this.meuBotao.

Porém, essa forma está como legacy e provavelmente em um futuro próximo será depreciada (deprecated), pois possuem vários efeitos colaterais, então como devemos fazer?

Nova API de referenciamentos

A partir da versão 16.3.0 do React, foi disponibilizado uma nova API chamada de createRef, e é exatamente através dela que devemos referenciar nossos componentes ou elementos do DOM. O uso deve ser feito da seguinte maneira:

  • Criar uma propriedade de classe para armazenar o ref.
  • Passar essa propriedade para quem deve ser referenciado.

Criando a propriedade de classe

Através do constructor (construtor), podemos criar essa propriedade da classe:

constructor(props) {
    super(props)
    this.meuBotao = React.createRef()
}

Se você preferir, podemos evitar a necessidade de uso do React fazendo a importação da função createRef, da seguinte maneira:

import React, { createRef } from "react"

// ... demais códigos

constructor(props) {
    super(props)
    this.meuBotao = createRef()
}

Fica a seu critério e gosto particular para decidir de qual forma utilizar.

Agora que já temos onde salvar o nosso referenciado, precisamos apenas realizar a referência.

Referenciando o componente

Para vincular nosso componente para a propriedade this.meuBotao, continuamos utilizando o atributo ref:

<MeuBotao ref={ this.meuBotao }/>

Apenas passamos a propriedade de classe que foi criada através da função createRef.

Acessando uma referência

Para acessar a referência dentro de alguma função ficou um pouco diferente, antes podíamos fazer algo do tipo:

this.meuBotao.focus()

Porém, com essa nova API, a nossa referência fica dentro de current, portanto, para acessar um botão, por exemplo, devemos fazer:

this.meuBotao.current.focus()

Vale observar que:

  • Se o referenciado é um componente de classe do React, o current recebe esse componente montado
  • Se o referenciado é um elemento HTML, o current irá receber o elemento do DOM ao qual aquele HTML está associado.

Referenciando através de callbacks

Também podemos realizar referencias através de callbacks:

<MeuBotao ref={ meuBotao => this.meuBotao = meuBotao }/>

Porém, aqui entra um detalhe: se fizermos dessa maneira, o React irá chamar o ref duas vezes; a primeira com null e a segunda com a referência de fato. Isso acontece porque novas instâncias são criadas para cada render, então o React precisa limpar a referência antiga para setar a nova.

Vale lembrar que apesar de existir uma nova API para realizar a referência, a forma através de callbacks ainda será suportada.

Redirecionando uma referência

Em alguns casos, você pode querer acessar a referência de uma referência (não recomendado; isso irá contra o encapsulamento de componentes), porém, tudo é possível e cada caso é um caso. Para tal necessidade foi disponibilizada a função forwardRef. Dessa maneira, conseguimos referenciar um filho como se fosse o próprio pai, por exemplo:

<MeuBotao ref={ this.meuBotao }/>

Essa referência será feita para a instância do componente MeuBotao, porém, eu quero acessar o button que está sendo renderizado pelo MeuBotao; como podemos fazer isso? Basicamente devemos repassar o ref recebido pelo MeuBotao para o button:

const MeuBotao = React.forwardRef(({ children }, ref) => (
    <button ref={ ref }>
        { children }
    </button>
))

Observação: assim como foi feita com o createRef, a função forwardRef também pode ser importada e usada de forma isolado ao React.

Repare que estamos utilizando a função forwardRef; sem ela não seria possível receber o ref para repassá-lo para nosso filho, a função irá devolver um componente do React.

Saiba mais

Quando o referenciado é desmontado, a referência recebe o valor null.

Componentes Funcionais (Functional Components) não podem ser referenciados, isso porque eles não possuem a instância de uma classe. Caso seja necessário, você pode convertê-lo para um Componente de Classe (Class Component).

Apensar de Componentes Funcionais não poderem ser referenciados, dentro deles você pode utilizar o atributo ref e fazer referências para outros componentes ou elementos HTML sem problemas.

Referências são atualizadas antes dos ciclos de vida: componentDidMount e componentDidUpdate.

Conclusão

Nesse artigo eu falei um pouco sobre referências de componentes ou elementos HTML, expliquei o novo jeito de fazer com a createRef e também expliquei como passar uma referência de pai para filhos com o forwardRef.

E aí, você já conhecia as novas APIs? Não deixe de comentar.

Até a próxima!