<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marcoshsc</title>
    <description>The latest articles on DEV Community by Marcoshsc (@marcoshsc).</description>
    <link>https://dev.to/marcoshsc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F899276%2F9c012a92-4a52-4c83-a881-32d5f9ef4f86.jpeg</url>
      <title>DEV Community: Marcoshsc</title>
      <link>https://dev.to/marcoshsc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcoshsc"/>
    <language>en</language>
    <item>
      <title>Simplificando seu código React usando closures</title>
      <dc:creator>Marcoshsc</dc:creator>
      <pubDate>Sun, 31 Jul 2022 01:51:43 +0000</pubDate>
      <link>https://dev.to/marcoshsc/simplificando-seu-codigo-react-usando-closures-48gp</link>
      <guid>https://dev.to/marcoshsc/simplificando-seu-codigo-react-usando-closures-48gp</guid>
      <description>&lt;p&gt;Imagina o seguinte caso: você precisa fazer um formulário que lida com quatro diferentes campos: field1, field2, field3 e field4. Naturalmente, você cria o seu formulário seguindo essa estrutura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Formulario = () =&amp;gt; {
  const [field1, setField1] = useState("");
  const [field2, setField2] = useState("");
  const [field3, setField3] = useState("");
  const [field4, setField4] = useState("");

  return (
    &amp;lt;form onSubmit={...}&amp;gt;
      &amp;lt;input label="Field 1" value={field1} onChange={(e) =&amp;gt; setField1(e.target.value)} /&amp;gt;
      &amp;lt;input label="Field 2" value={field2} onChange={(e) =&amp;gt; setField2(e.target.value)} /&amp;gt;
      &amp;lt;input label="Field 3" value={field3} onChange={(e) =&amp;gt; setField3(e.target.value)} /&amp;gt;
      &amp;lt;input label="Field 4" value={field4} onChange={(e) =&amp;gt; setField4(e.target.value)} /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temos um estado para cada campo, controlamos cada um dos inputs com seu respectivo valor, e colocamos no onChange um callback que muda o valor de acordo com o que o usuário digitou. Até aqui tudo bem, certo? Bom... esse código tem um problema claro à primeira vista: a lógica do callback onChange de todos os inputs está localizada dentro da função render, coisa que dependendo do tamanho do componente e do callback passado, pode dificultar a manutenção no futuro.&lt;br&gt;
Pois bem: você se incomodou com isso e resolveu esse problema, extraindo todas as funções para callbacks no corpo do componente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Formulario = () =&amp;gt; {
  const [field1, setField1] = useState("");
  const [field2, setField2] = useState("");
  const [field3, setField3] = useState("");
  const [field4, setField4] = useState("");

  const handleChangeField1 = (e) =&amp;gt; {
    setField1(e.target.value)
  }

  const handleChangeField2 = (e) =&amp;gt; {
    setField2(e.target.value)
  }

  const handleChangeField3 = (e) =&amp;gt; {
    setField3(e.target.value)
  }

  const handleChangeField4 = (e) =&amp;gt; {
    setField4(e.target.value)
  }

  return (
    &amp;lt;form onSubmit={...}&amp;gt;
      &amp;lt;input label="Field 1" value={field1} onChange={handleChangeField1} /&amp;gt;
      &amp;lt;input label="Field 2" value={field2} onChange={handleChangeField2} /&amp;gt;
      &amp;lt;input label="Field 3" value={field3} onChange={handleChangeField3} /&amp;gt;
      &amp;lt;input label="Field 4" value={field4} onChange={handleChangeField4} /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resolvido agora, certo? Bom, melhorou um pouco porém ainda temos um problema: se tivermos 10 campos, precisaremos declarar 10 callbacks? Ora, analisando os quatro callbacks criados, podemos perceber que todos eles fazem tarefas parecidas: receber um evento e setar o valor do estado com &lt;code&gt;e.target.value&lt;/code&gt;.&lt;br&gt;
E como poderíamos resolver este problema? Afinal, a função onChange está esperando um callback neste exato formato que criamos. Será que existe uma maneira de criar um callback neste formato, que se adapta a cada diferente estado do input? Bom, para isso podemos utilizar uma estrutura no javascript chamada de &lt;strong&gt;closures&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  O que são closures?
&lt;/h2&gt;

&lt;p&gt;Um &lt;strong&gt;closure&lt;/strong&gt; é um conceito que se refere à uma função que é criada dentro de outra função, com acesso ao seu contexto léxico. Para simplificar, confere esse exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const outer = (name) =&amp;gt; {
  const inner = () =&amp;gt; {
    console.log(name)
  }
  inner()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que, dentro da função outer, é declarada uma função inner, sem parâmetros, porém que consegue acessar o parâmetro name da função outer (contexto léxico), e printar o valor na sequência. Após sua criação, a função inner pode ser utilizada normalmente, da forma como foi criada. Por exemplo, caso fosse executado &lt;code&gt;outer('marcos')&lt;/code&gt;, seria imprimido a string 'marcos' no console.&lt;br&gt;
Closures também podem ser usados como geradores de funções mais simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getPropertySetter = (propertyName) =&amp;gt; {
  const setProperty = (obj, value) =&amp;gt; {
    obj[propertyName] = value 
  }
  return setProperty
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com esse closure, posso simplificar o processo de modificar uma propriedade em um objeto, por exemplo. Observe que a função externa recebe somente o nome da propriedade, e retorna uma função nova, que recebe um objeto e o valor da propriedade, e faz a atribuição desse valor à propriedade cujo nome foi informado na função mais externa, no objeto recebido. Essa função poderia ser utilizada da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const setName = getPropertySetter("name");
const setAge = getPropertySetter("age");
const obj = {};
setName(obj, "marcos");
setAge(obj, 22);
console.log(obj);
// output = { name: 'marcos', age: 22 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que um closure te permite criar funções que geram outras funções, que resolvem problemas de uma maneira mais simples ou mais conveniente.&lt;/p&gt;

&lt;h2&gt;
  
  
  De volta ao problema
&lt;/h2&gt;

&lt;p&gt;Agora que você sabe o que é um closure, como podemos utilizar esse conceito para melhorar o código do formulário? Vamos identificar as semelhanças com os exemplos de closure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Precisamos passar um callback para o onChange, com um parâmetro que é o evento&lt;/li&gt;
&lt;li&gt;Porém, algo que muda para cada input é a função setter do estado.&lt;/li&gt;
&lt;li&gt;Logo, podemos criar um closure onde a função externa recebe o setter, e retornar então uma função interna com o formato que desejamos, que faz a tarefa comum:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleChange = (stateSetter) =&amp;gt; {
    const setFieldValue = (e) =&amp;gt; {
      stateSetter(e.target.value) 
    }
    return setFieldValue
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E podemos então reutilizar esse closure em todos os nossos inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
    &amp;lt;form onSubmit={...}&amp;gt;
      &amp;lt;input label="Field 1" value={field1} onChange={handleChange(setField1)} /&amp;gt;
      &amp;lt;input label="Field 2" value={field2} onChange={handleChange(setField2)} /&amp;gt;
      &amp;lt;input label="Field 3" value={field3} onChange={handleChange(setField3)} /&amp;gt;
      &amp;lt;input label="Field 4" value={field4} onChange={handleChange(setField4)} /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que agora, temos a lógica separada da renderização, e o número de campos pode aumentar infinitamente, que não precisaremos escrever novos callbacks, somente reutilizar nosso closure. Ao final, nosso componente fica da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Formulario = () =&amp;gt; {
  const [field1, setField1] = useState("");
  const [field2, setField2] = useState("");
  const [field3, setField3] = useState("");
  const [field4, setField4] = useState("");

  const handleChange = (stateSetter) =&amp;gt; {
    const setFieldValue = (e) =&amp;gt; {
      stateSetter(e.target.value) 
    }
    return setFieldValue
  }

  return (
    &amp;lt;form onSubmit={...}&amp;gt;
      &amp;lt;input label="Field 1" value={field1} onChange={handleChange(setField1)} /&amp;gt;
      &amp;lt;input label="Field 2" value={field2} onChange={handleChange(setField2)} /&amp;gt;
      &amp;lt;input label="Field 3" value={field3} onChange={handleChange(setField3)} /&amp;gt;
      &amp;lt;input label="Field 4" value={field4} onChange={handleChange(setField4)} /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Temos um componente muito mais limpo e escalável.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Closures são muito importantes no javascript, especialmente no React. Podem te ajudar e muito a deixar seu código mais limpo e simples, e facilitar a reutilização de código. Aqui eu dei somente um exemplo de como poderiam ser utilizados no React, porém eles são aplicáveis a qualquer lógica semelhante ao que mostrei aqui.&lt;/p&gt;

&lt;p&gt;E ai, já sabia do que se tratavam os closures? Aprendeu algo novo? Deixa ai nos comentários! Muito obrigado pela leitura, e até o próximo post!&lt;/p&gt;

</description>
      <category>react</category>
      <category>closure</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
