(React + this + bind) = só sei que é assim

Desmistificando o limiar entre JavaScript e React Só sei que é assim agora é passado! vamos conhecer melhor esses recursos e como eles podem influenciar na performance quando você desenvolve aplicações em React. Em um componente React você pode definir métodos de classe e então os utilizar no método render de seu componente. Exemplo: class
(React + this + bind) = só sei que é assim

Desmistificando o limiar entre JavaScript e React

Só sei que é assim agora é passado! vamos conhecer melhor esses recursos e
como eles podem influenciar na performance quando você desenvolve aplicações em
React.

Em um componente React você pode definir métodos de classe e então os utilizar
no método render de seu componente. Exemplo:

class
 extends React.Component {

() {
    console.dir(this); // "this" é quem vai chamar o método risada
    return "HAHAHAHA!!!";
  }

  render() {
    return
;
  }
}

ReactDOM.render(, document.getElementById('root'));

Nesse exemplo utilizei o método risada dentro do método render como
this.risada porque dentro do render, a palavra-chave this refere-se à
instância do componente associado com o elemento da DOM que representa esse
componente.

Internamente o React vai garantir de que aquele “this” dentro de seus métodos
de classe se refere à instância. Embora o JavaScript não vincula a instância
automaticamente quando você usa uma referência para o método risada.

A linhaconsole.dir no métodorisada vai mostrar corretamente a instância do
componente porque aquele método foi chamado diretamente do método render
especificando o chamador explícitamente (this). Você poderá ver o objeto
RisadaCruel no console quando você executar o código abaixo:

Acontece que quando você usa o mesmo método em uma situação em que esse método
não vai ser executado instantaneamente como um event handler da vida, “quem” irá
chamar aquele método não vai mais ser explícito e a linha do console.dir não
vai reportar a instância do componente como antes.

No codigo acima o React invoca o método evento quando você clica na string,
mas não lhe dará acesso à instância do componente dentro dela fazendo com que
você receba um undefinedna sua cara quando você clicar na string. Esse é um
problema se seu método de classe precisa ter acesso a coisas como this.props e
this.state. Isso simplesmente não irá funcionar do jeito que você imagina.

Calma, existem varias solucoes para esse problema. Você pode abraçar o método em
uma função inline ou usar a chamada .bind para forçar o método a lembrar quem
o chamou. Essas são soluções ok se seus componentes não são atualizados tão
frequentemente. Você pode também otimizar o método bind do JavaScript chamando
ele lá no construtor da classe do seu componente ao invés de fazer isso no
método render que é chamado constantemente.

Agora você pode estar se perguntando… Mas pera ai, porque eu faria isso? não
entendi nada! E eu lhe diria em seguida.. Sim, isso seria totalmente normal meu
caro aventureiro, vamos entender isso melhor!

Entendendo um pouquinho de otimização em React

Imagine a situação em que você esteja passando funções/eventos com a chamada
.bind visando definir uma ação para os botões de cada item de uma lista que
você esteja criando lá dentro do metodo render. Acontece que em JavaScript,
quando o método bind recebe o seu primeiro argumento this em sua chamada,
isso é justamente para definir explicitamente quem chamou aquela função, ou
seja, o contexto no qual você quer que essa função seja executada. Assim o
método bind retorna uma função novinha em folha que retorna uma chamada a sua
função original forçando esse this, ou seja, fazendo com que a função original
reconheça quem for que seja o argumento this como quem a chamou,
consequentemente quem é o seu contexto de chamada. Como seria essa função na
vida real?

2 exemplos simplificados da implementação da função bind:

function
(algumaFuncao, algumThis) {
    return function() {
        return algumaFuncao.apply( algumThis, arguments );
    };
}

 objetoLegal = {};
 algumaFuncao = function() {};
 funcaoLegal = bind(algumaFuncao, objetoLegal);
// funcaoLegal agiria como se fosse: objetoLegal.algumaFuncao();


Function.prototype.
 = function(algumThis) {
    return function() {
        return this.apply(algumThis, arguments);
    }
};

 objetoFamoso = {};
 algumaFuncao = function() {};
 funcaoFamosa = this.algumaFuncao.bind(objetoFamoso);
// funcaoFamosa agiria como se fosse: objetoFamoso.algumaFuncao();
  • A implementação oficial do método bind é muito mais sofisticada do que isso.
  • Existem dois métodos para definição explícita de contexto em JavaScript, o
    método call e o apply que vieram antes do método bind com o advento do
    ES6.
  • A diferença entre o método call e o apply é que o apply lhe deixa chamar a
    função com o parâmetro arguments sendo um array tipo
    algumaFuncao.apply(algumThis, arrayDeArgumentos). Já o call você terá que
    chamar com os parâmetros explicitamente separados por vírgulas tipo
    algumaFuncao.call(algumThis, arg1, arg2, ...). Uma mnemónica útil para
    entender a diferença entre esses dois métodos é “A para array e C para
    comma.”.** Créditos por essa explicação para
    flatline.**
  • Use o método bind quando quiser que essa função seja chamada posteriormente
    com um determinado contexto. Use call ou apply quando você quiser invocar a
    função imediatamente modificando ou forçando o contexto.

Uhum, depois disso tudo que você escreveu ainda nao sei o que que isso tem haver

com otimização!


Tyler The Sloth by allheartsgoboom

Acontece que em JavaScript objetos complexos como as funções são instâncias
diferentes e possuem identidades diferentes, sendo assim a verificação de
igualdade superficial que o React faz entre os componentes sempre produz
resultado falso, ou seja, sempre resulta em diferença! 😨

Isso faz com que o React renderize novamente esses componentes que receberam
essa função novinha e única (em termos de referência) que foi criada toda vez
que o método bind foi chamado naquele evento dentro do método render do
componente.

A mesma coisa acontece se ao invés de utilizar uma função você esteja passando
um array para cada item dessa lista no render, porque em JavaScript, o
literal array é a mesma coisa que chamar new Array()que cria uma nova
instância (única em termos de referência) de um array. Isso destrói (muito
trágico) completamente toda otimização de renderização pura do React!

Outra situação onde uma função novinha é criada no render causando essa coisa
toda que eu falei:

class
 extends PureComponent {
  render() {
    return ;
  }
}

Isso mesmo, essa arrow
function

é de fato uma função que não foge a regra, nesse caso vai ser também uma
entidade única para cada Input como mostra o caso acima. É interessante saber
dessas coisas né? já fiz “errado” muitas vezes! mas calma lá em, esse errado na
verdade é um pseudo errado porque cada caso é um caso e na maioria das vezes a
performance não vai ser um ponto crítico para você. A não ser, é claro, que seja
o caso de uma lista gigante, animações, etc. Enfim, se seu componente atualiza
constantemente.

Voltando ao exemplo do nosso componente RisadaCruel

Uma melhor solução para esse método atualmente é habilitar o recurso de
class-fields (campos de classe) do ECMAScript (no qual esta em stage-3) através
do Babel e simplesmente utilizar uma arrow function para os handlers:

class RisadaCruel extends React.Component {


render() {
    return (
     
Hello World
); } }

Nice! mas pera ai, habilitar o recurso de class-fields em stage-3**? Como é
que é esse stage aí?**

No TC39, o comitê que desenvolve o JavaScript no qual seus membros são empresas
(entre outros camaradas como também todos os principais fornecedores de
navegadores) e cada proposta de um recurso para a linguagem passa por vários
estágios de maturidade, começando pelo estágio 0. O stage-3 ou estágio 3 que foi
mencionado anteriormente, significa que a proposta de tal recurso está
praticamente finalizada e agora precisa de feedback de implementações e usuários
para progredir ainda mais. Mais detalhes do TC e dos outros estágios
aqui.

fecharPost.bind(this);

É isso aí pessoal! espero ter desmistificado um pouco do limiar entre o que é
realmente JavaScript do que é realmente coisa do React e também como o React se
comporta com o uso “as vezes” inadequado do JavaScript em uma aplicação React. É
sabendo um pouco mais da ferramenta que utilizamos que podemos escrever
aplicações ainda melhores e mais performáticas.

Fim!!!

E valeu por ter chegado até aqui! 🤓

Está interessado ou já é explorador do mundo React? dê uma olhada no meu outro
post sobre tutoriais fantásticos e onde habitam!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *