{"componentChunkName":"component---src-templates-docs-js","path":"/docs/higher-order-components.html","result":{"data":{"markdownRemark":{"html":"<p>Um componente de ordem superior (HOC, do inglês Higher-Order Component) é uma técnica avançada do React para reutilizar a lógica de um componente. HOCs não são parte da API do React, per se. Eles são um padrão que surgiu da própria natureza de composição do React.</p>\n<p>Concretamente, <strong>um componente de ordem superior é uma função que recebe um componente e retorna um novo componente.</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">higherOrderComponent</span><span class=\"token punctuation\">(</span>WrappedComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Enquanto um componente transforma props em UI, um componente de ordem superior transforma um componente em outro componente.</p>\n<p>HOCs são comuns em bibliotecas externas ao React, como o <a href=\"https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">connect</code></a> do Redux e o <a href=\"http://facebook.github.io/relay/docs/en/fragment-container.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">createFragmentContainer</code></a> do Relay.</p>\n<p>Neste documento, nós vamos discutir porque componentes de ordem superior são úteis e como escrever o seu.</p>\n<h2 id=\"use-hocs-for-cross-cutting-concerns\"><a href=\"#use-hocs-for-cross-cutting-concerns\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Usar HOCs para características transversais. </h2>\n<blockquote>\n<p><strong>Nota</strong></p>\n<p>Anteriormente, nós recomendamos mixins como uma forma de lidar com características transversais. Desde então, percebemos que mixins criam mais problemas do que trazem valor. <a href=\"/blog/2016/07/13/mixins-considered-harmful.html\">Leia mais</a> sobre porque nós deixamos os mixins de lado e como você pode fazer a transição dos seus componentes existentes.</p>\n</blockquote>\n<p>Componentes são a unidade primária de reutilização de código no React. Contudo, pode-se perceber que alguns padrões não se encaixam tão facilmente em componentes tradicionais.</p>\n<p>Por exemplo, digamos que você tem um componente <code class=\"gatsby-code-text\">CommentList</code> que subscreve-se a uma fonte externa de dados para renderizar uma lista de comentários:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CommentList</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// \"DataSource\" é uma fonte de dados global</span>\n      comments<span class=\"token operator\">:</span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getComments</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Subscreve-se às mudanças</span>\n    DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">addChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Limpa o listener</span>\n    DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">removeChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Atualiza o state do componente sempre que a fonte de dados muda</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      comments<span class=\"token operator\">:</span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getComments</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>comments<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">comment</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n          <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Comment</span></span> <span class=\"token attr-name\">comment</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>comment<span class=\"token punctuation\">}</span></span> <span class=\"token attr-name\">key</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>comment<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Depois, você escreve um componente que se subscreve a um blog post, o qual segue um padrão similar:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">BlogPost</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      blogPost<span class=\"token operator\">:</span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getBlogPost</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">addChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">removeChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      blogPost<span class=\"token operator\">:</span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getBlogPost</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">TextBlock</span></span> <span class=\"token attr-name\">text</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>blogPost<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><code class=\"gatsby-code-text\">CommentList</code> e <code class=\"gatsby-code-text\">BlogPost</code> não são idênticos - eles chamam métodos diferentes de <code class=\"gatsby-code-text\">DataSource</code> e renderizam saídas diferentes. Mas muito de suas implementações é igual:</p>\n<ul>\n<li>Em <code class=\"gatsby-code-text\">mount</code>, adicione um change listener para <code class=\"gatsby-code-text\">DataSource</code>.</li>\n<li>Dentro do listener, chame <code class=\"gatsby-code-text\">setState</code> sempre que a fonte de dados mudar.</li>\n<li>Em <code class=\"gatsby-code-text\">unmount</code>, remova o change listener.</li>\n</ul>\n<p>Você pode imaginar que em uma aplicação grande, esse mesmo padrão de subscrever-se a <code class=\"gatsby-code-text\">DataSource</code> e chamar <code class=\"gatsby-code-text\">setState</code> irá ocorrer várias vezes. Nós queremos uma abstração que permita-nos definir essa lógica em um único lugar e compartilhá-la com vários componentes. Isso é onde componentes de ordem superior se destacam.</p>\n<p>Nós podemos escrever uma função que cria componentes, como <code class=\"gatsby-code-text\">CommentList</code> e <code class=\"gatsby-code-text\">BlogPost</code>, que subscrevem-se a <code class=\"gatsby-code-text\">DataSource</code>. A função irá aceitar como um dos seus argumentos um componente filho que recebe o dado assinado como uma prop. Vamos chamar a função de <code class=\"gatsby-code-text\">withSubscription</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> CommentListWithSubscription <span class=\"token operator\">=</span> <span class=\"token function\">withSubscription</span><span class=\"token punctuation\">(</span>\n  CommentList<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">(</span><span class=\"token parameter\">DataSource</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getComments</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> BlogPostWithSubscription <span class=\"token operator\">=</span> <span class=\"token function\">withSubscription</span><span class=\"token punctuation\">(</span>\n  BlogPost<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">(</span><span class=\"token parameter\">DataSource<span class=\"token punctuation\">,</span> props</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getBlogPost</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>O primeiro parâmetro é um componente encapsulado. O segundo parâmetro acessa os dados que estamos interessados, dado um <code class=\"gatsby-code-text\">DataSource</code> e as props atuais.</p>\n<p>Quando <code class=\"gatsby-code-text\">CommentListWithSubscription</code> e <code class=\"gatsby-code-text\">BlogPostWithSubscription</code> são renderizados, <code class=\"gatsby-code-text\">CommentList</code> e <code class=\"gatsby-code-text\">BlogPost</code> receberão uma prop <code class=\"gatsby-code-text\">data</code> com os dados mais recentes obtidos de <code class=\"gatsby-code-text\">DataSource</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// A função recebe um componente...</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">withSubscription</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent<span class=\"token punctuation\">,</span> selectData</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...e retorna outro componente...</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">extends</span> React<span class=\"token punctuation\">.</span>Component <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        data<span class=\"token operator\">:</span> <span class=\"token function\">selectData</span><span class=\"token punctuation\">(</span>DataSource<span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ... que lida com a subscrição...</span>\n      DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">addChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      DataSource<span class=\"token punctuation\">.</span><span class=\"token function\">removeChangeListener</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        data<span class=\"token operator\">:</span> <span class=\"token function\">selectData</span><span class=\"token punctuation\">(</span>DataSource<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ... e renderiza o componente encapsulado com os dados novos!</span>\n      <span class=\"token comment\">// Note que nós passamos diretamente qualquer prop adicional</span>\n      <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">WrappedComponent</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">}</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">this</span><span class=\"token punctuation\">.</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Note que um HOC não modifica o componente de entrada, nem utiliza herança para copiar seu comportamento. Em vez disso, um HOC <em>compõe</em> o componente original ao <em>envolvê-lo</em> (wrapping) em um componente container. Um HOC é uma função pura sem efeitos colaterais.</p>\n<p>E é isso! O componente encapsulado recebe todas as props do container, junto de uma nova prop, <code class=\"gatsby-code-text\">data</code>, o qual a utiliza para renderizar sua saída. O HOC não se preocupa com o como ou o porquê de seus dados serem usados, e o componente encapsulado não se preocupa de onde os dados vieram.</p>\n<p>Por <code class=\"gatsby-code-text\">withSubscription</code> ser uma função normal, você pode adicionar quantos argumentos quiser. Por exemplo, você pode querer fazer o nome da prop <code class=\"gatsby-code-text\">data</code> ser configurável, para continuar a isolar o HOC do componente encapsulado. Ou você pode aceitar um argumento que configura <code class=\"gatsby-code-text\">shouldComponentUpdate</code>, ou um que configura a fonte de dados. Todos esses casos são possíveis porque o HOC tem controle total sobre como o componente é definido.</p>\n<p>Como componentes, o contrato entre <code class=\"gatsby-code-text\">withSubscription</code> e o componente encapsulado é completamente baseado em props. Isso faz com que seja fácil trocar um HOC por outro, desde que eles providenciem as mesmas props para o componente encapsulado. Isso pode ser útil se você mudar de bibliotecas para obtenção de dados, por exemplo.</p>\n<h2 id=\"dont-mutate-the-original-component-use-composition\"><a href=\"#dont-mutate-the-original-component-use-composition\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Não alterar o componente original. Usar composição. </h2>\n<p>Resista à tentação de modificar o prototype de um componente (ou alterá-lo de qualquer outra forma) dentro de um HOC.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">logProps</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">InputComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token class-name\">InputComponent</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">componentDidUpdate</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prevProps</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Current props: '</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Previous props: '</span><span class=\"token punctuation\">,</span> prevProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// O fato de estarmos retornando a entrada original é uma dica de que ela sofreu mutação.</span>\n  <span class=\"token keyword\">return</span> InputComponent<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// EnhancedComponent criará logs sempre que uma prop for recebida</span>\n<span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">logProps</span><span class=\"token punctuation\">(</span>InputComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Existem alguns problemas nisso. Primeiro, o componente de entrada não pode ser reutilizado separadamente do componente melhorado. Mais crucialmente, se você aplicar outro HOC para <code class=\"gatsby-code-text\">EnhancedComponent</code> que <em>também</em> altera <code class=\"gatsby-code-text\">componentDidUpdate</code>, a funcionalidade do primeiro HOC será sobrescrita! Esse HOC também não funcionará com componentes funcionais, os quais não possuem métodos de ciclo de vida.</p>\n<p>Realizar mutações em HOCs podem causar “vazamentos” - o consumidor deve saber como eles são implementados para evitar conflitos com outros HOCs.</p>\n<p>Em vez de mutações, HOCs devem utilizar composição, encapsulando o componente de entrada em um componente container:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">logProps</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">extends</span> React<span class=\"token punctuation\">.</span>Component <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">componentDidUpdate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prevProps</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Current props: '</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Previous props: '</span><span class=\"token punctuation\">,</span> prevProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Encapsula o componente de entrada em um container, sem alterá-lo. Excelente!</span>\n      <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">WrappedComponent</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">this</span><span class=\"token punctuation\">.</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Esse HOC possui a mesma funcionalidade que a sua versão com mutação e evita o potencial de ocorrer conflitos. Ele funciona igualmente bem com componentes funcionais e controlados. E por ser uma função pura, pode ser combinado com outros HOCs, ou até com si mesmo.</p>\n<p>Você deve ter notado similaridades entre HOCs e um padrão chamado <strong>componentes container</strong>. Componentes container são parte de uma estratégia de separação de responsabilidade entre preocupações de alto nível e baixo nível. Containers gerenciam coisas como subscrições e state, e passam props para componentes que lidam com coisas como renderização da UI. HOCs utilizam containers como parte de sua implementação. Você pode pensar em HOCs como definições de componentes container com parâmetros.</p>\n<h2 id=\"convention-pass-unrelated-props-through-to-the-wrapped-component\"><a href=\"#convention-pass-unrelated-props-through-to-the-wrapped-component\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Convenção: Passar props não relacionadas para o componente encapsulado </h2>\n<p>HOCs adicionam características a um componente. Eles não devem alterar drasticamente o seu contrato. É esperado que um componente retornado de um HOC tenha uma interface similar ao do componente encapsulado.</p>\n<p>HOCs devem passar props que não são relacionadas às suas preocupações específicas. A maioria dos HOCs possuem um método render que se parece com algo assim:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Filtra props extras que são específicas a esse HOC e não devem ser</span>\n  <span class=\"token comment\">// passadas para o componente encapsulado.</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> extraProp<span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>passThroughProps <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Injeta props no componente encapsulado.</span>\n  <span class=\"token comment\">// Estes geralmente são valores do state ou métodos da instância.</span>\n  <span class=\"token keyword\">const</span> injectedProp <span class=\"token operator\">=</span> someStateOrInstanceMethod<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Passa as props para o componente encapsulado.</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">WrappedComponent</span></span>\n      <span class=\"token attr-name\">injectedProp</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>injectedProp<span class=\"token punctuation\">}</span></span>\n      <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">passThroughProps</span><span class=\"token punctuation\">}</span></span>\n    <span class=\"token punctuation\">/></span></span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Essa convenção ajuda a garantir que HOCs são tão flexíveis e reutilizáves quanto possível.</p>\n<h2 id=\"convention-maximizing-composability\"><a href=\"#convention-maximizing-composability\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Convenção: Maximizando composabilidade </h2>\n<p>Nem todos os HOCs são iguais. Às vezes eles aceitam apenas um único argumento, o componente encapsulado:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> NavbarWithRouter <span class=\"token operator\">=</span> <span class=\"token function\">withRouter</span><span class=\"token punctuation\">(</span>Navbar<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Normalmente, HOCs aceitam argumentos adicionais. Neste exemplo do Relay, um objeto de configuração é usado para especificar uma dependência de dados de um componente:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> CommentWithRelay <span class=\"token operator\">=</span> Relay<span class=\"token punctuation\">.</span><span class=\"token function\">createContainer</span><span class=\"token punctuation\">(</span>Comment<span class=\"token punctuation\">,</span> config<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>A assinatura mais comum para HOCs se parece com isso:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// `connect` do React Redux</span>\n<span class=\"token keyword\">const</span> ConnectedComment <span class=\"token operator\">=</span> <span class=\"token function\">connect</span><span class=\"token punctuation\">(</span>commentSelector<span class=\"token punctuation\">,</span> commentActions<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>CommentList<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><em>O Que?!</em> Se você quebrar isso em partes, é mais fácil de ver o que está acontecendo.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// connect é uma função que retorna outra função</span>\n<span class=\"token keyword\">const</span> enhance <span class=\"token operator\">=</span> <span class=\"token function\">connect</span><span class=\"token punctuation\">(</span>commentListSelector<span class=\"token punctuation\">,</span> commentListActions<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// A função retornada é um HOC, que retorna um componente que está conectado</span>\n<span class=\"token comment\">// à store do Redux</span>\n<span class=\"token keyword\">const</span> ConnectedComment <span class=\"token operator\">=</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span>CommentList<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Em outras palavras, <code class=\"gatsby-code-text\">connect</code> é uma função de ordem superior que retorna um componente de ordem superior!</p>\n<p>Essa forma pode parecer confusa ou desnecessária, mas ela possui uma propriedade útil. HOCs com um único argumento, como o retornado pela função <code class=\"gatsby-code-text\">connect</code>, possuem a assinatura <code class=\"gatsby-code-text\">Componente =&gt; Componente</code>. Funções cujo tipo de saída é igual ao tipo da entrada são muito fáceis de se compor.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// Em vez de fazer isso...</span>\n<span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">withRouter</span><span class=\"token punctuation\">(</span><span class=\"token function\">connect</span><span class=\"token punctuation\">(</span>commentSelector<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>WrappedComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// ... Você pode usar uma conveniência de composição de funções</span>\n<span class=\"token comment\">// compose(f, g, h) é o mesmo que (...args) => f(g(h(...args)))</span>\n<span class=\"token keyword\">const</span> enhance <span class=\"token operator\">=</span> <span class=\"token function\">compose</span><span class=\"token punctuation\">(</span>\n  <span class=\"token comment\">// Ambos são HOCs com um único argumento</span>\n  withRouter<span class=\"token punctuation\">,</span>\n  <span class=\"token function\">connect</span><span class=\"token punctuation\">(</span>commentSelector<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span>WrappedComponent<span class=\"token punctuation\">)</span></code></pre></div>\n<p>(Essa mesma propriedade também permite que <code class=\"gatsby-code-text\">connect</code> e outros enhancer-style HOCs sejam usados como decoradores, uma proposta experimental do JavaScript.)</p>\n<p>A função de conveniência <code class=\"gatsby-code-text\">compose</code> é disponibilizada por várias bibliotecas de terceiros, incluindo lodash (como o <a href=\"https://lodash.com/docs/#flowRight\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">lodash.flowRight</code></a>), <a href=\"https://redux.js.org/docs/api/compose.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Redux</a>, e <a href=\"https://ramdajs.com/docs/#compose\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Ramda</a>.</p>\n<h2 id=\"convention-wrap-the-display-name-for-easy-debugging\"><a href=\"#convention-wrap-the-display-name-for-easy-debugging\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Convenção: Envolver o nome de exibição para melhor depuração </h2>\n<p>Os componentes container criados por HOCs aparecem no <a href=\"https://github.com/facebook/react-devtools\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Developer Tools</a> como qualquer outro componente. Para facilitar a depuração, escolha um nome de exibição que comunique que o componente é o resultado de um HOC.</p>\n<p>A técnica mais comum é encapsular o nome de exibição do componente encapsulado. Então, se o seu componente de ordem superior se chama <code class=\"gatsby-code-text\">withSubscription</code>, e o nome de exibição do componente encapsulado é <code class=\"gatsby-code-text\">CommentList</code>, use o nome de exibição <code class=\"gatsby-code-text\">WithSubscription(CommentList)</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">withSubscription</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">WithSubscription</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span><span class=\"token comment\">/* ... */</span><span class=\"token punctuation\">}</span>\n  WithSubscription<span class=\"token punctuation\">.</span>displayName <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">WithSubscription(</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token function\">getDisplayName</span><span class=\"token punctuation\">(</span>WrappedComponent<span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">)</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> WithSubscription<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">getDisplayName</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> WrappedComponent<span class=\"token punctuation\">.</span>displayName <span class=\"token operator\">||</span> WrappedComponent<span class=\"token punctuation\">.</span>name <span class=\"token operator\">||</span> <span class=\"token string\">'Component'</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"caveats\"><a href=\"#caveats\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Ressalvas </h2>\n<p>Componentes de ordem superior vêm com algumas ressalvas que não são imediatamente óbvias se você for novo no React.</p>\n<h3 id=\"dont-use-hocs-inside-the-render-method\"><a href=\"#dont-use-hocs-inside-the-render-method\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Não usar HOCs dentro do método render </h3>\n<p>O algoritmo de comparação do React (chamado <a href=\"/docs/reconciliation.html\">Reconciliação</a>) usa a identidade do componente para determinar se ele deve atualizar a sub-árvore existente ou jogá-la fora e montar uma nova. Se o componente que foi retornado do <code class=\"gatsby-code-text\">render</code> é idêntico (<code class=\"gatsby-code-text\">===</code>) ao componente do render anterior, o React atualizará a sub-árvore comparando-a recursivamente com uma nova. Se elas não forem iguais, a sub-árvore anterior será completamente desmontada.</p>\n<p>Normalmente, você não precisa se preocupar com isso. Mas isso é importante em HOCs porque não se pode aplicar um HOC em um componente dentro do método render de um componente:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Uma nova versão de EnhancedComponent é criada toda vez que render for chamado</span>\n  <span class=\"token comment\">// EnhancedComponent1 !== EnhancedComponent2</span>\n  <span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span>MyComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// Isso faz com que a sub-árvore seja completamente</span>\n  <span class=\"token comment\">// desmontada/remontada todas as vezes!</span>\n  <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">EnhancedComponent</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>O problema aqui não é só na performance - remontar um componente causa a perda de todo o seu state e todos os seus filhos.</p>\n<p>Em vez disso, aplique HOCs fora da definição do componente para que o componente resultante seja criado apenas uma vez. Então, sua identidade será consistente pelas renderizações. De qualquer forma, isso geralmente é o que você quer.</p>\n<p>Nesses casos raros em que é preciso aplicar um HOC dinamicamente, isso também pode ser feito dentro dos métodos de ciclo de vida do componente, ou no seu construtor.</p>\n<h3 id=\"static-methods-must-be-copied-over\"><a href=\"#static-methods-must-be-copied-over\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Métodos estáticos devem ser propagados </h3>\n<p>As vezes é útil definir um método estático em um componente do React. Por exemplo, containers do Relay expõem um método estático <code class=\"gatsby-code-text\">getFragment</code> para facilitar a composição de fragmentos do GraphQL.</p>\n<p>Mas, quando se aplica um HOC a um componente, o componente original é encapsulado com um componente container. Isso significa que o novo componente não possui nenhum dos métodos estáticos do componente original.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// Defina um método estático</span>\nWrappedComponent<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">staticMethod</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token comment\">/*...*/</span><span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// Agora aplique um HOC</span>\n<span class=\"token keyword\">const</span> EnhancedComponent <span class=\"token operator\">=</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span>WrappedComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// O EnhancedComponent não possui métodos estáticos</span>\n<span class=\"token keyword\">typeof</span> EnhancedComponent<span class=\"token punctuation\">.</span>staticMethod <span class=\"token operator\">===</span> <span class=\"token string\">'undefined'</span> <span class=\"token comment\">// true</span></code></pre></div>\n<p>Para resolver isso, você pode copiar os métodos no container antes de retorná-lo:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">Enhance</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span><span class=\"token comment\">/*...*/</span><span class=\"token punctuation\">}</span>\n  <span class=\"token comment\">// Deve-se saber exatamente qual método copiar :(</span>\n  Enhance<span class=\"token punctuation\">.</span>staticMethod <span class=\"token operator\">=</span> WrappedComponent<span class=\"token punctuation\">.</span>staticMethod<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> Enhance<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Porém, isso requer que você saiba exatamente quais métodos precisam ser copiados. A biblioteca <a href=\"https://github.com/mridgway/hoist-non-react-statics\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">hoist-non-react-statics</a> pode ser usada para copiar automaticamente todos os métodos estáticos que não são do React:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">import</span> hoistNonReactStatic <span class=\"token keyword\">from</span> <span class=\"token string\">'hoist-non-react-statics'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">enhance</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">WrappedComponent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">Enhance</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span><span class=\"token comment\">/*...*/</span><span class=\"token punctuation\">}</span>\n  <span class=\"token function\">hoistNonReactStatic</span><span class=\"token punctuation\">(</span>Enhance<span class=\"token punctuation\">,</span> WrappedComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> Enhance<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Outra solução possível é exportar o método estático do próprio componente, separadamente.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// Em vez de...</span>\nMyComponent<span class=\"token punctuation\">.</span>someFunction <span class=\"token operator\">=</span> someFunction<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> MyComponent<span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// ... exporte o método separadamente...</span>\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> someFunction <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// ... e no módulo que está consumindo, importe ambos</span>\n<span class=\"token keyword\">import</span> MyComponent<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> someFunction <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./MyComponent.js'</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"refs-arent-passed-through\"><a href=\"#refs-arent-passed-through\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Refs não são passadas diretamente </h3>\n<p>Enquanto a convenção para componentes de ordem superior é passar diretamente todas as props para o componente encapsulado, isso não funciona para refs. Isso acontece porque <code class=\"gatsby-code-text\">ref</code> não é exatamente uma prop - tal como <code class=\"gatsby-code-text\">key</code>, ela é tratada de maneira especial pelo React. Se uma ref for adicionado a um elemento cujo componente é o resultado de um HOC, a ref referenciará à instância mais externa do componente container, não ao componente encapsulado.</p>\n<p>A solução para esse problema é usar a API <code class=\"gatsby-code-text\">React.forwardRef</code> (introduzida com o React 16.3). <a href=\"/docs/forwarding-refs.html\">Saiba mais sobre ela na seção de encaminhamento de refs</a>.</p>","frontmatter":{"title":"Componentes de Ordem Superior","next":null,"prev":null},"fields":{"path":"content/docs/higher-order-components.md","slug":"docs/higher-order-components.html"}}},"pageContext":{"slug":"docs/higher-order-components.html"}},"staticQueryHashes":[]}