<?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>Forem: jennypollard</title>
    <description>The latest articles on Forem by jennypollard (@jennypollard).</description>
    <link>https://forem.com/jennypollard</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%2F970336%2F83982778-ab96-49d7-a960-e8d34e313468.png</url>
      <title>Forem: jennypollard</title>
      <link>https://forem.com/jennypollard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jennypollard"/>
    <language>en</language>
    <item>
      <title>Что делает React Compiler?</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Wed, 15 Jan 2025 19:14:28 +0000</pubDate>
      <link>https://forem.com/jennypollard/chto-dielaiet-react-compiler-3dh3</link>
      <guid>https://forem.com/jennypollard/chto-dielaiet-react-compiler-3dh3</guid>
      <description>&lt;p&gt;Реакт Компилятор (react compiler) - это инструмент для оптимизации React-приложений. Компилятор включается в работу во время сборки приложения и трансформирует код так, чтобы избежать ненужные ререндеры. &lt;/p&gt;

&lt;p&gt;Компилятор анализирует код, составляет его упрощенное представление, находит места, которые можно оптимизировать, трансформирует выбранный код. Реакт Компилятор предполалагет, что код удовлетворяет &lt;a href="https://react.dev/reference/rules" rel="noopener noreferrer"&gt;Правилам Реакта&lt;/a&gt; - такой код не сломается от оптимизаций компилятора. Если код не удовлетворяет Правилам, то он будет проигнорирован.&lt;/p&gt;

&lt;p&gt;Компилятор применяет к коду, как минимум, две трансформации: мемоизирует результат рендера и результат вычисления выражений внутри компонентов.&lt;/p&gt;

&lt;h3&gt;
  
  
  Мемоизация результата рендера
&lt;/h3&gt;

&lt;p&gt;Результатом рендера я называю выражение, которое возвращается из компонента: &lt;code&gt;return &amp;lt;div&amp;gt;{items}&amp;lt;/div&amp;gt;&lt;/code&gt;, в этом примере &lt;code&gt;&amp;lt;div&amp;gt;{items}&amp;lt;/div&amp;gt;&lt;/code&gt; - результат рендера. Результат рендера зависит от пропсов и промежуточных значений, вычисленных внутри компонента. Назовем эти значения зависимостями выражения. Когда результат рендера остается постоянным при одних и тех же зависимостях, вычисление выражения можно пропустить. Для этого Реакт Компилятор вставит код, запоминающий последний результат вычисления:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Если выражение вычисляется первый раз, то вычисляет выражение, сохраняет результат в кэш, сохраняет зависимости в кэш.&lt;/li&gt;
&lt;li&gt;Если выражение вычисляется повторно, сравнивает новые значения зависимостей с сохраненными в кэше:
&lt;/li&gt;
&lt;li&gt;Если они равны, использует закэшированное значение выражения.
&lt;/li&gt;
&lt;li&gt;Если они разные, вычисляет выражение с новыми зависимостями, сохраняет результат вычисления и зависимости в кэш.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Такой компонент:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Div&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;data-x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Реакт Компилятор преобразует вот так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_c&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/compiler-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;data-x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Можно догадаться, что в строке &lt;code&gt;const $ = _c(3)&lt;/code&gt; Реакт Компилятор создает локальный кэш на 3 элемента. В действительности, &lt;code&gt;c&lt;/code&gt; из react/compiler-runtime вызывает внутри себя &lt;a href="https://github.com/facebook/react/blob/main/compiler/packages/react-compiler-runtime/src/index.ts#L28" rel="noopener noreferrer"&gt;React.useMemo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;В случае, когда компонент использует хуки или контекст, сгенерированный код выглядет немного сложнее, но идея таже: сравнить текущие зависимости компонента с закэшированными, если они поменялись закэшировать новые зависимости, вычислить новое значение, закэшировать новое значение.&lt;/p&gt;

&lt;p&gt;Код в примере выше аналогичен оборачиванию компонента в &lt;a href="https://dev.to/jennypollard/react-memo-pomnitie-mienia-4ke3"&gt;memo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Мемоизация выражений
&lt;/h3&gt;

&lt;p&gt;В примере выше, jsx-выражение зависило только от пропсов компонента. Часто в компонентах вычисляются промежуточные значения, которые подставляются в jsx-выражения. Эти промежуточные значения также могут быть мемоизированы. Для этого Реакт Компилятор определит зависимости выражения и вставит код для кэширования всего выражения на основе этих зависимостей.&lt;/p&gt;

&lt;p&gt;Рассмотрим пример, в котором внутри компонента происходит вычисление:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В этом примере &lt;code&gt;&amp;lt;main&amp;gt;{name}&amp;lt;/main&amp;gt;&lt;/code&gt; - это jsx-выражение, его зависимость - переменная &lt;code&gt;name&lt;/code&gt;, которая в свою очередь вычисляется выше выражением &lt;code&gt;props.fullname.split(' ')[0]&lt;/code&gt;. Выражение &lt;code&gt;props.fullname.split(' ')[0]&lt;/code&gt; зависит только от пропсы &lt;code&gt;fullname&lt;/code&gt;.&lt;br&gt;
Реакт Компилятор преобразует этот компонент следующим образом:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_c&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/compiler-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Реакт Компилятор закэширует &lt;code&gt;props.fullname&lt;/code&gt; и результат вычисления &lt;code&gt;name&lt;/code&gt;. Если пропса &lt;code&gt;fullname&lt;/code&gt; поменяется, выражение будет вычислено и закэшировано еще раз. Этот код аналогичен оборачиванию вычисления &lt;code&gt;name&lt;/code&gt; в &lt;code&gt;useMemo&lt;/code&gt; в исходном компоненте:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Включение Реакт Компилятора может не принести ощутимой пользы в проекте, в котором осознанно используются useMemo и memo.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Техника Помодоро vs Результат</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Sat, 30 Nov 2024 21:27:33 +0000</pubDate>
      <link>https://forem.com/jennypollard/tiekhnika-pomodoro-taimier-ostanovilsia-370o</link>
      <guid>https://forem.com/jennypollard/tiekhnika-pomodoro-taimier-ostanovilsia-370o</guid>
      <description>&lt;p&gt;Долой помодоро. Занималась задачей полчаса, сфокусированно, результата нет, но есть обманчивое ощущение что делаешь все правильно. Одна помидорка в день, десять помидорок в день, так несколько дней и нет результата. Но есть помидорки. Не работает. &lt;/p&gt;

&lt;p&gt;Нужен результат, маленький результат прямо сейчас, хоть два предложения, хоть понимание следующего шага, хоть строчка кода. За 25 минут, или за 5, или за 77, если требуется. Но нужен результат.&lt;/p&gt;

&lt;p&gt;Какая разница, 20 минут помидорка, 25 или 30? Какая разница какой перерыв отдыха между ними? Какая разница какое ты используешь приложение?&lt;/p&gt;

&lt;p&gt;Помодоро оттягивает на себя внимание, оттягивает его от результата. А результат это единственное что важно.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>React Signals: как устроены сигналы в React</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Fri, 28 Apr 2023 13:46:48 +0000</pubDate>
      <link>https://forem.com/jennypollard/sighnaly-v-react-kak-2e49</link>
      <guid>https://forem.com/jennypollard/sighnaly-v-react-kak-2e49</guid>
      <description>&lt;p&gt;Следуя трендам, можно было обнаружить для себя React Signals. Возможно, вам попадался такой фрагмент кода:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@preact/signals-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Код вызывает удивление — как это сделано? Почему &lt;code&gt;App&lt;/code&gt; обновляется при изменении &lt;code&gt;count&lt;/code&gt;? Что позволило так сделать? Похоже на хуки, но нет, хуки нельзя использовать вне компонента…&lt;/p&gt;

&lt;h3&gt;
  
  
  Найдем код &lt;code&gt;@preact/signals-react&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Пакеты берутся из npm-реестра, найдем &lt;code&gt;@preact/signals-react&lt;/code&gt; на npmjs.com. На &lt;a href="https://www.npmjs.com/package/@preact/signals-react" rel="noopener noreferrer"&gt;странице пакета&lt;/a&gt; есть ссылка на репозиторий модуля на &lt;a href="https://github.com/preactjs/signals" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. В репозитории есть несколько директорий: docs, patches, scripts, packages. Первые три нам сейчас не интересны — это документация и какие-то вспомогательные вещи, посмотрим в packages. В packages есть core, preact, react. preact — нас сейчас не интересует, core — нечто очень важное и общее, но нам нужно конкретное — react. Внутри найдем &lt;a href="https://github.com/preactjs/signals/blob/b08732dfcb55b7e99df2fd644cb61b5b14acdb9e/packages/react/src/index.ts" rel="noopener noreferrer"&gt;src/index.ts&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  С чего начать — код выполняемый при инициализации модуля
&lt;/h3&gt;

&lt;p&gt;Разберемся, что происходит при инициализации модуля, посмотрим, что делает код, выполняемый при импорте модуля. Проигнорируем, для начала, определения функций и внутренних переменных, у нас останется:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JsxRuntimeModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsxRuntime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JsxRuntimeModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsxRuntimeDev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*   */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*   */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*  */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*  */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/**/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/**/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Decorate Signals so React renders them as &amp;lt;Text&amp;gt; components.&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="na"&gt;$typeof&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactElemType&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Последний блок кода (с &lt;code&gt;Object.defineProperties&lt;/code&gt;) добавляет всем сигналам возможность рендериться: &lt;code&gt;$$typeof&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;props&lt;/code&gt;, &lt;code&gt;ref&lt;/code&gt; — свойства всех React-элементов.&lt;/p&gt;

&lt;p&gt;Остановимся подробней на первой части, в ней участвуют: &lt;code&gt;jsx&lt;/code&gt;, &lt;code&gt;jsxs&lt;/code&gt; (из &lt;code&gt;react/jsx-runtime&lt;/code&gt;), &lt;code&gt;jsx&lt;/code&gt;, &lt;code&gt;jsxs&lt;/code&gt; (из &lt;code&gt;react/jsx-dev-runtime&lt;/code&gt;), &lt;code&gt;createElement&lt;/code&gt; из React и некая функция &lt;code&gt;WrapJsx&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Что такое jsx-runtime?
&lt;/h3&gt;

&lt;p&gt;React-компоненты преобразуются в вызовы &lt;code&gt;React.createElement&lt;/code&gt;, &lt;code&gt;jsx&lt;/code&gt; или &lt;code&gt;jsxs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Например, такой код:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click Me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;будет преобразован компилятором в:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_jsx&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;_jsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Click Me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;_jsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;_jsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В зависимости от настроек js-компилятора (например, babel), вместо &lt;code&gt;React.createElement&lt;/code&gt; может быть &lt;code&gt;jsx&lt;/code&gt; из &lt;code&gt;react/jsx-runtime&lt;/code&gt;, будем считать их эквивалентными. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.createElement&lt;/code&gt; — это функция создающая  React-элемент. У нее три аргумента: &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;children&lt;/code&gt;. Первый аргумент &lt;code&gt;type&lt;/code&gt; — это тип элемента, может быть:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;строкой — для хост-элеметов: &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;объектом — в случае экзотичных React-элементов: &lt;code&gt;forwardRef&lt;/code&gt;, &lt;code&gt;memo&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;функцией — для функциональных или класс-компонентов.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Второй аргумент &lt;code&gt;config&lt;/code&gt; — это объект, содержащий в себе пропсы элемента, &lt;code&gt;ref&lt;/code&gt; и &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Последний аргумент &lt;code&gt;children&lt;/code&gt; — список дочерних элементов. Точно такую же роль выполняют функции &lt;code&gt;jsx&lt;/code&gt;, &lt;code&gt;jsxs&lt;/code&gt;, &lt;code&gt;jsxDev&lt;/code&gt; — создают React-элементы, имеют такие же аргументы. &lt;/p&gt;

&lt;p&gt;Вернемся к коду инициализации модуля:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JsxRuntimeModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsxRuntime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JsxRuntimeModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsxRuntimeDev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*   */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*   */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*  */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/*  */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/**/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxDev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="cm"&gt;/**/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WrapJsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JsxPro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxDEV&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Теперь понятно, что модуль переопределяет функции создания React-элементов результатом вызова функции &lt;code&gt;WrapJsx&lt;/code&gt;. Каждая функция: &lt;code&gt;jsx&lt;/code&gt;, &lt;code&gt;jsxs&lt;/code&gt;, &lt;code&gt;jsxDEV&lt;/code&gt;, &lt;code&gt;createElment&lt;/code&gt; преобразуется с помощью &lt;code&gt;WrapJsx&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Что делает функция-декоратор &lt;code&gt;WrapJsx&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Посмотрим код функции &lt;code&gt;WrapJsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WrapJsx&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$$typeof&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ReactMemoType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$$typeof&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ReactForwardRefType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WrapJsx&lt;/code&gt; вызывается с единственным аргументом &lt;code&gt;jsx&lt;/code&gt; — оригинальной функцией создания React-элемента и возвращает функцию с такими же как у &lt;code&gt;jsx&lt;/code&gt; аргументами. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;WrapJsx&lt;/code&gt; обрабатывает четыре сценария:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Функциональный компонент или класс-компонент:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Если создается React-элемент, тип у которого — функция, значит элементу соответствует фукнциональный компонент или класс-компонент. Например, для такого jsx-выражения: &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;Foo&amp;gt;text&amp;lt;/Foo&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; под условие выше подходит &lt;code&gt;Foo&lt;/code&gt;. Внутри условия вызывается оригинальная функция &lt;code&gt;jsx&lt;/code&gt;, но вместо исходного &lt;code&gt;type&lt;/code&gt; передается &lt;code&gt;ProxyFunctionalComponent(type)&lt;/code&gt;, это эквивалентно оборачиванию &lt;code&gt;Foo&lt;/code&gt; в &lt;code&gt;ProxyFunctionalComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Экзотичные React-элементы:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$$typeof&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ReactMemoType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$$typeof&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ReactForwardRefType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProxyFunctionalComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Если тип элемента — объект, значит создается экзотичный React-элемент, их два: &lt;code&gt;memo&lt;/code&gt; и &lt;code&gt;forwardRef&lt;/code&gt;. Оба эти элемента ссылаются на функциональный компонент, который нужно отрендерить. Элемент &lt;code&gt;memo&lt;/code&gt; ссылается на компонент через свойство &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;forwardRef&lt;/code&gt; ссылается через свойство &lt;code&gt;render&lt;/code&gt;. Во фрагменте выше, они также оборачиваются в &lt;code&gt;ProxyFunctionalComponent&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Хост-компоненты.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Хост-компоненты (&lt;code&gt;div&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt; и тд) попадают в третью ветку, в этом случае &lt;code&gt;type&lt;/code&gt; — это строка.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Для таких элементов просматривают все пропсы и, если среди них есть экземпляр Сигнала, он заменяется на его значение &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Таким образом, декоратор &lt;code&gt;WrapJsx&lt;/code&gt; оборачивает все пользовательские компоненты в &lt;code&gt;ProxyFunctionalComponent&lt;/code&gt;. При каждом обновлении (рендере) пользовательского компонента будет сначала происходить вызов &lt;code&gt;ProxyFunctionalComponent&lt;/code&gt;. Так как можно быть уверенным, что это происходит в момент обновления, внутри &lt;code&gt;ProxyFunctionalComponent&lt;/code&gt; можно использовать хуки, создавать локальный компоненту стейт, подписываться на события. &lt;code&gt;@preact/signals-react&lt;/code&gt; использует эту возможность, чтобы отслеживать обращения к Сигналам внутри компонента и вызывать обновление компонента, когда Сигнал изменяется.&lt;/p&gt;

</description>
      <category>react</category>
      <category>signal</category>
    </item>
    <item>
      <title>npm i или npm ci?</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Thu, 23 Feb 2023 13:38:09 +0000</pubDate>
      <link>https://forem.com/jennypollard/npm-i-ili-npm-ci-1cn8</link>
      <guid>https://forem.com/jennypollard/npm-i-ili-npm-ci-1cn8</guid>
      <description>&lt;h2&gt;
  
  
  npm i vs npm ci — какую команду использовать.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  npm i (npm install)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npm i&lt;/code&gt; устанавливает пакеты и их зависимости в директорию &lt;code&gt;node_modules&lt;/code&gt;. По-умолчанию, список пакетов берется из раздела &lt;code&gt;dependencies&lt;/code&gt; в &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm&lt;/code&gt; обновляет файл &lt;code&gt;package-lock.json&lt;/code&gt; после любых измений &lt;code&gt;package.json&lt;/code&gt; или &lt;code&gt;node_modules&lt;/code&gt;. То есть, если в результате выполнения какой-либо команды &lt;code&gt;npm&lt;/code&gt;, будет обновлен &lt;code&gt;package.json&lt;/code&gt; или содержимое &lt;code&gt;node_modules&lt;/code&gt;, то будет обновлен &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package-lock.json&lt;/code&gt; описывает фактическое дерево пакетов, которое было уставновлено и нужен для того, чтобы выполнение &lt;code&gt;npm i&lt;/code&gt; приводило к одному и тому же набору пакетов. Другими словами, &lt;code&gt;package-lock.json&lt;/code&gt; это описание того, что установлено в &lt;code&gt;node_modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i&lt;/code&gt; может устанавливать пакеты по-одному, по-умолчанию &lt;code&gt;npm i&lt;/code&gt; добавляет установленный пакет в раздел &lt;code&gt;dependencies&lt;/code&gt; (и обновляет &lt;code&gt;package-lock.json&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  npm ci
&lt;/h3&gt;

&lt;p&gt;Команда &lt;code&gt;npm ci&lt;/code&gt; похожа на &lt;code&gt;npm i&lt;/code&gt; — тоже устанавливает зависимости, но предназначена для установки зависимостей с чистого листа — при сборке приложения, в релизных пайплайнах, в проверках пулреквестов, используется автоматикой. &lt;code&gt;npm ci&lt;/code&gt; быстрее, чем &lt;code&gt;npm i&lt;/code&gt; и имеет существенные отличия:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;удаляет &lt;code&gt;node_modules&lt;/code&gt; перед установкой.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm ci&lt;/code&gt; требует для работы наличие &lt;code&gt;package-lock.json&lt;/code&gt;, иначе получим ошибку:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;npm ERR! cipm can only install packages with an existing package-lock.json or npm-shrinkwrap.json with lockfileVersion &amp;gt;= 1. Run an install with npm@5 or later to generate it, then try again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm ci&lt;/code&gt; не может устанавливать пакеты по-одному, устанавливает все сразу как описано в &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm ci&lt;/code&gt; не обновляет &lt;code&gt;package-lock.json&lt;/code&gt; и &lt;code&gt;package.json&lt;/code&gt;, так как предназначен для автоматики, а в этом случае репозиторий только на чтение.&lt;/li&gt;
&lt;li&gt;если версии пакетов в &lt;code&gt;package.json&lt;/code&gt; и &lt;code&gt;package-lock.json&lt;/code&gt; расходятся, команда завершится с ошибкой:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;npm ERR! cipm can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with &lt;code&gt;npm install&lt;/code&gt; before continuing.&lt;br&gt;
npm ERR! Invalid: lock file's &lt;a href="mailto:lodash.get@4.4.2"&gt;lodash.get@4.4.2&lt;/a&gt; does not satisfy &lt;a href="mailto:lodash.get@4.4.0"&gt;lodash.get@4.4.0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Иногда в &lt;code&gt;node_modules&lt;/code&gt; могут накапливаться проблемы (например, рассинхрон фактических и ожидаемых версий пакетов), для таких случаев &lt;code&gt;npm ci&lt;/code&gt; — быстрый способ переустановить все зависимости.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/fr/@hooverpaul55?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Paul Teysen&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/bukjsECgmeU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>npm</category>
    </item>
    <item>
      <title>О чем написать пост - Выбираем тему для поста</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Sat, 28 Jan 2023 14:28:23 +0000</pubDate>
      <link>https://forem.com/jennypollard/o-chiem-napisat-post-vybiraiem-tiemu-dlia-slieduiushchiegho-posta-1m7h</link>
      <guid>https://forem.com/jennypollard/o-chiem-napisat-post-vybiraiem-tiemu-dlia-slieduiushchiegho-posta-1m7h</guid>
      <description>&lt;p&gt;Уже в самом начале я столкнулась с этим и хочется сформилуровать для себя некоторую претензию на фреймворк, пусть это будет начало.&lt;/p&gt;

&lt;h3&gt;
  
  
  Рецепты
&lt;/h3&gt;

&lt;p&gt;В среде в которой мы работаем, часто возникают вопросы у коллег — как добиться какого-то поведения в коде. Эти вопросы могут служить темой для поста. Ответь для себя на такой вопрос, сделай минимальный пример. С примерами может помочь &lt;a href="https://codesandbox.io/" rel="noopener noreferrer"&gt;codesandbox&lt;/a&gt; или &lt;a href="https://stackblitz.com/" rel="noopener noreferrer"&gt;stackblitz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Еще источником вдохновения могут служить вопросы и комментарии на &lt;a href="https://stackoverflow.com/" rel="noopener noreferrer"&gt;stackoverlow&lt;/a&gt; или аналогичных платформах. Можно дать новую жизнь своим ответам или найти интересную идею в комментариях к вопросам и ответам.&lt;/p&gt;

&lt;h3&gt;
  
  
  Покопаться в исходниках
&lt;/h3&gt;

&lt;p&gt;Каждый день мы используем какой-нибудь фреймворк, технологию. Используем какие-то функции, возможно, моделируя для себя их реализацию на основе их поведения и прочитанного в документации — для нас они черный ящик. Можно заглянуть “под капот”, найти реализацию в исходниках, доуточнить свою модель и рассказать об этом.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ограничить усилия сверху
&lt;/h3&gt;

&lt;p&gt;Если только начинаешь, объемное, подробное исследование не подойдет. Большой объем демотивирует, очень много шагов для выполнения — по сложности тянет на проект, который займет много времени и даст сравнительно мало положительной обратной связи. К тому же, может не хватить квалификации, а дальнейшее погружение может затянуть на неопределенное время. Поэтому есть высокие шансы, что пост будет заброшен, в сравнении с меньшим по объему. Подробное исследование само по себе прекрасно, полезно, но цель здесь — завершенная самостоятельная идея, оформленная в виде поста.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Продолжай писать…&lt;/em&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Что такое React Fiber - React Fiber Architecture</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Thu, 29 Dec 2022 13:25:50 +0000</pubDate>
      <link>https://forem.com/jennypollard/chto-takoie-react-fiber-react-fiber-architecture-2cho</link>
      <guid>https://forem.com/jennypollard/chto-takoie-react-fiber-react-fiber-architecture-2cho</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;React Fiber — это реализация стека вызовов, специализированная для React-компонентов. Единичный файбер можно считать виртуальным фреймом стека.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Перевод статьи Эндрю Кларка “React Fiber Architecture” &lt;a href="https://github.com/acdlite/react-fiber-architecture" rel="noopener noreferrer"&gt;https://github.com/acdlite/react-fiber-architecture&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Введение
&lt;/h3&gt;

&lt;p&gt;React Fiber это продолжающееся переделывание ключевых алгоритмов React и кульминация двух лет исследований проводимых командой разработки.&lt;/p&gt;

&lt;p&gt;Цель React Fiber — улучшить приемлемость React в таких областях как анимация, лейаут и жесты. Его главное свойство — инкрементальная отрисовка — способность разделить работу по отрисовке на части и распределить ее на несколько кадров.&lt;/p&gt;

&lt;p&gt;Другие ключевые функции React Fiber: способность приостановить, прекратить или переиспользовать результат работы при поступлении новых обновлений, способность назначить приоритет разным типам обновлений, новые примитивы для параллельного выполнения.&lt;/p&gt;

&lt;h3&gt;
  
  
  Об этом документе
&lt;/h3&gt;

&lt;p&gt;Fiber вводит несколько новых концепций, которые сложно понять просто смотря код. Этот документ начинался как коллекция заметок, которые автор делал разбираясь реализацией Fiber в коде React. По мере того, как заметки росли, автор осознал что они могут быть полезны другим тоже.&lt;/p&gt;

&lt;p&gt;Автор попытается использовать самый ясный язык, насколько это возможно, и попытается давать ясные определения ключевым терминам, вместо использования жаргона.&lt;/p&gt;

&lt;p&gt;Пожалуйста, имейте в виду, что автор не входит в команду React и не говорит от имени команды. Это неофициальный документ. Автор просил членов команды React проверить этот документ на предмет неточностей.&lt;/p&gt;

&lt;p&gt;К тому же, работа над Fiber ведется сейчас — этот проект скорее всего претерпит значительный рафакторинг. Также продолжается работа автора по документированию архитектуры Fiber в этом документе. Улучшения и предложения приветствуются.&lt;/p&gt;

&lt;p&gt;Цель автора — сформировать понимание архитектуры Fiber достаточное для того, чтобы ориентироваться в его изменениях по мере развития, и, в конечном счете, чтобы быть способным внести свои изменения в React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Перед тем как начать…
&lt;/h3&gt;

&lt;p&gt;Автор настойчиво рекомендует, чтобы читатель для начала ознакомился со следующими статьями:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://facebook.github.io/react/blog/2015/12/18/react-components-elements-and-instances.html" rel="noopener noreferrer"&gt;React Components, Elements, and Instances&lt;/a&gt;. Компонент — часто перегруженный термин, важно уверенно понимать, что он означает.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://facebook.github.io/react/docs/reconciliation.html" rel="noopener noreferrer"&gt;Reconciliation&lt;/a&gt;. Высокоуровневое описание алгоритма реконсилиации.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/reactjs/react-basic" rel="noopener noreferrer"&gt;React Basic Theoretical Concepts&lt;/a&gt;. Описание концептуальной модели React неотягощенная реализацией. Что-то из этого может быть непонятно при первом чтение — это нормально, станет понятней позже.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://facebook.github.io/react/contributing/design-principles.html" rel="noopener noreferrer"&gt;React Design Principles&lt;/a&gt;. Обратите особое внимание на раздел про планирование — в нем даны хорошие объяснения причинам, стоящим за React Fiber.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Обзор
&lt;/h3&gt;

&lt;p&gt;Пожалуйста, ознакомьтесь с разделом “Перед тем как начать”, если вы этого еще не сделали.&lt;/p&gt;

&lt;p&gt;Перед тем как погрузиться в новые вещи, давайте вспомним несколько концепций.&lt;/p&gt;

&lt;h3&gt;
  
  
  Что такое реконсилиация?
&lt;/h3&gt;

&lt;p&gt;Реконсилиация — алгоритм, используемый React-ом, чтобы вычислить разницу между двумя деревьями для определения того, какие части должны быть обновлены.&lt;/p&gt;

&lt;p&gt;Обновление — изменение в данных используемых для отрисовки приложения. Обычно, это результат вызова &lt;code&gt;setState&lt;/code&gt;. В конечном счете обновление приводит к переотрисовке.&lt;/p&gt;

&lt;p&gt;Центральная идея API React-а — считать что обновления вызывают переотрисовку всего приложения. Это позволяет разработчикам рассуждать декларативно, вместо того, чтобы беспокоиться о том, как эффективно перевести приложение из одного состояния в другое.&lt;/p&gt;

&lt;p&gt;На самом деле, переотрисовка всего приложения на каждое обновление работает только для самых простых приложений, в реальных приложениях так делать слишком дорого с точки зрения производительности. React использует оптимизации, которые создают видимость полного обновления приложения, но в тоже время поддерживают отличную производительность. Основная масса этих оптимизаций это часть процесса называемого &lt;strong&gt;реконсилиацией&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Реконсилиация это алгоритм лежащий в основе виртуального DOM. Высокоуровневое описание примерно такое: когда отрисовывается React приложение, генерируется дерево структур описывающих приложение и сохраняется в памяти. Это дерево затем отправляется среде отрисовки — например, в случае браузерного приложения, дерево переводится в набор операций над DOM. Когда приложение обновляется (обычно из-за &lt;code&gt;setState&lt;/code&gt;), генерируется новое дерево. Новое дерево сравнивается с предыдущим для определения, какие операции нужны, чтобы обновить отрисованное приложение.&lt;/p&gt;

&lt;p&gt;Хотя Fiber это попытка переписать с нуля реконсилятор, высокоуровневое описание &lt;a href="https://reactjs.org/docs/reconciliation.html" rel="noopener noreferrer"&gt;алгоритма в документации React&lt;/a&gt; будет почти такое же. Ключевые моменты такие:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Предполагается, что компоненты разных типов производят существенно разные деревья. React не будет пытаться их сравнивать, просто заменит старое дерево на новое.&lt;/li&gt;
&lt;li&gt;Определение разницы между двумя списками элементов осуществляется с помощью ключей. Ключи должны быть “стабильные, предсказуемые и уникальные”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Реконсилиация vs Отрисовка
&lt;/h3&gt;

&lt;p&gt;DOM браузера это только одна из сред отрисовки в которой может работать React, отрисовка в других средах, iOS и Android, достигается средствами React Native. По этой причине термин “виртуальный &lt;em&gt;DOM&lt;/em&gt;” немного некорректен.&lt;/p&gt;

&lt;p&gt;React спроектирован так, чтобы процесс реконсилиации и отрисовки были раздельными фазами, благодаря этому React поддерживает разные среды отрисовки. Реконсилятор вычисляет, какие части дерева элементов были изменены, затем отрисовщик использует эту информацию, чтобы обновить отрисованное приложение.&lt;/p&gt;

&lt;p&gt;Это разделение на механизмы отрисовки и реконсиляции означает, что React DOM и React Native могут использовать собственные отрисовщики и один и тот же реконсилятор, предоставленный React.&lt;/p&gt;

&lt;p&gt;Fiber — новый реконсилятор. В основном, реконсилятор не связан с отрисовкой, хотя отрисовщикам нужно будет поддержать новую архитектуру и воспользоваться её преимуществами.&lt;/p&gt;

&lt;h3&gt;
  
  
  Планирование
&lt;/h3&gt;

&lt;p&gt;Планирование — процесс определения когда &lt;em&gt;работа&lt;/em&gt; должна быть выполнена.&lt;/p&gt;

&lt;p&gt;Работа — любые вычисления, которые должны быть выполнены. &lt;em&gt;Работа&lt;/em&gt; это обычно результат обновления (например, по причине вызова &lt;code&gt;setState&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/docs/design-principles.html" rel="noopener noreferrer"&gt;Принципы Архитектуры&lt;/a&gt; React задокументировали это настолько хорошо, что можно привести цитату:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;В текущей реализации React обходит дерево элементов рекурсивно и вызывает функцию отрисовки всего обновленного дерева в течение одного тика. Однако, в будущем React может откладывать некоторые обновления, чтобы избежать падения частоты кадров.&lt;br&gt;
Это основной мотив архитектуры React. Некоторые популярные библиотеки реализуют push-подход, когда вычисления происходят по мере поступления новых данных. Однако React придерживается pull-подхода, когда вычисления могут быть отложены до того момента, когда они необходимы.&lt;br&gt;
React это не универсальная библиотека для обработки данных, это библиотека для построения пользовательских интерфейсов. Мы думаем, что React занимает однозначное место в приложении, чтобы знать, какие вычисления сейчас уместны, а какие нет.&lt;br&gt;
Если что-то находится за пределами экрана, мы можем отложить логику связанную с этим. Если данные прибывают быстрее, чем частота кадров, мы можем объединять обновления в группы. Чтобы избежать падение частоты кадров, мы можем отдавать приоритет работе связанной со взаимодействием пользователя с интерфейсом (например, анимация вызванная нажатием на кнопку), чем менее важной фоновой работе (например, отрисовка нового контента разгруженного из сети).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ключевые вещи:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;В пользовательском интерфейсе нет необходимости применять каждое обновление сразу — это может быть нерациональным и быть причиной для потери частоты кадров и ухудшения пользовательского опыта.&lt;/li&gt;
&lt;li&gt;У разных типов обновлений, разные приоритеты. Обновление связанное с анимацией должно быть выполнено быстрее, чем, скажем, обновление из хранилища данных.&lt;/li&gt;
&lt;li&gt;Push-подход требует от приложения (от разработчика) решить, как спланировать работу. Pull-подход позволяет фреймворку (React) быть умнее и принимать такие решения за разработчика.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Сейчас React не пользуется преимуществами планирования в значительной степени. Обновление немедленно приводит к полной перерисовке поддерева. Реконструирование основного алгоритма React так, чтобы воспользоваться преимуществами планирования — это движущая идея Fiber.&lt;/p&gt;

&lt;p&gt;Теперь мы готовы погрузиться в реализацию Fiber. Следующая секция более техническая, чем та, которую мы только что обсудили. Пожалуйста, убедитесь что вам комфортно с предыдущим материалом, прежде чем продолжить.&lt;/p&gt;

&lt;h3&gt;
  
  
  Что такое файбер?
&lt;/h3&gt;

&lt;p&gt;Мы приступаем к обсуждению центральной части архитектуры React Fiber. Файбер (fiber) — это абстракция более низкого уровня, чем обычно думают разработчики приложений. Если вы отчаялись в попытках понять ее, не разочаровывайтесь. Пробуйте и в конечном счете будет понятно. (Когда станет, пожалуйста, предложите как улучшить этот раздел.)&lt;/p&gt;

&lt;p&gt;Поехали!&lt;/p&gt;




&lt;p&gt;Мы определили, что главная цель Fiber — дать возможность React воспользоваться преимуществами планирования. В частности, нам нужно иметь возможность:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;приостанавливать работу и возвращаться к ней позже.&lt;/li&gt;
&lt;li&gt;назначить приоритет разным типам работы.&lt;/li&gt;
&lt;li&gt;переиспользовать результат ранее выполненной работы.&lt;/li&gt;
&lt;li&gt;прервать работу, если результат ее больше не нужен.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Чтобы это сделать, в первую очередь нам нужен способ разделить работу на блоки. В некотором смысле, файбер является таким блоком. Файбер представляет собой &lt;strong&gt;единицу работы&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Чтобы двигаться дальше, вернемся к концепции &lt;a href="https://github.com/reactjs/react-basic#transformation" rel="noopener noreferrer"&gt;“React-компонент как функция от данных”&lt;/a&gt;, которая обычно выражается как &lt;code&gt;v = f(d)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Из этого следует, что отрисовка React-приложения схожа с вызовом функции, тело которой содержит вызовы других функций и так далее. Эта аналогия полезна для понимания файбер.&lt;/p&gt;

&lt;p&gt;Как правило, компьютеры отслеживают выполнение программы с помощью стека вызовов. Когда функция вызывается, в стек вызовов добавляется новый фрейм стека. Фрейм стека представляет работу, которая выполняется данной функцией.&lt;/p&gt;

&lt;p&gt;При работе с пользовательскими интерфейсами проблема заключается в том, что если слишком много работы выполняется за раз, это может привести к тому, что анимация потеряет в частоте кадров и будет выглядеть прерывистой. Более того, такая работа может быть ненужной, если она сменяется более новым обновлением. В этом месте сравнение UI компонентов и функций перестает работать, потому что у компонентов более специфичные задачи, чем у функции в общем.&lt;/p&gt;

&lt;p&gt;Более новые браузеры (и React Native) реализуют API, которое учитывает эту проблему: &lt;code&gt;requestIdleCallback&lt;/code&gt; планирует выполнение менее приоритетных функций во время периода бездействия, а &lt;code&gt;requestAnimationFrame&lt;/code&gt; планирует более приоритетные функции во время следующего кадра анимации. Проблема в том, что для использования этого API нужен способ разделить работу по отрисовке на инкрементальные единицы. Если полагаться только на стек вызовов, работа будет выполняться пока стек вызовов не опустеет.&lt;/p&gt;

&lt;p&gt;Правда было бы круто, если бы мы могли приспособить стек вызовов так, чтобы оптимизировать отрисовку интерфейса? Было бы супер, если бы мы могли произвольно прерывать стек вызовов и управлять фреймами стека вручную?&lt;/p&gt;

&lt;p&gt;Это и есть цель React Fiber. Файбер — это реализация стека вызовов, специализированная для React-компонентов. Единичный файбер можно считать &lt;strong&gt;виртуальным фреймом стека&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Польза от переделывания стека в том, что можно &lt;a href="https://www.facebook.com/groups/2003630259862046/permalink/2054053404819731/" rel="noopener noreferrer"&gt;сохранить фреймы стека в памяти&lt;/a&gt; и выполнять их как и когда захочется. Это критично для достижения наших требований к планированию.&lt;/p&gt;

&lt;p&gt;Помимо планирования, ручное управление фреймами стека раскрывает потенциал для параллелизма и границ ошибок. Мы рассмотрим эти темы в следующих секциях.&lt;/p&gt;

&lt;p&gt;В следующем разделе мы подробнее рассмотрим структуру файбера.&lt;/p&gt;

&lt;h3&gt;
  
  
  Структура файбера
&lt;/h3&gt;

&lt;p&gt;В конкретном смысле, файбер это JS-объект, который содержит информацию о компоненте, его входных данных и выходном результате.&lt;/p&gt;

&lt;p&gt;Файбер соответствует фрейму стека, но также соответствует экземпляру компонента. Перечислим некоторые важные поля файбера (не все):&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;type&lt;/code&gt; и &lt;code&gt;key&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;type&lt;/code&gt; и &lt;code&gt;key&lt;/code&gt; служат такой же цели, как и в случае React-элемента. Фактически, когда файбер создается из элемента, эти два поля просто копируются из него.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type&lt;/code&gt; ссылается на компонент соответствующий файберу. Для составных компонентов, &lt;code&gt;type&lt;/code&gt; это функция или класс компонента. Для хост-компонентов (&lt;code&gt;div&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt; и так далее), &lt;code&gt;type&lt;/code&gt; это строка.&lt;/p&gt;

&lt;p&gt;Концептуально, &lt;code&gt;type&lt;/code&gt; это функция (как в &lt;code&gt;v = f(d)&lt;/code&gt;), выполнение которой отслеживается стековым фреймом.&lt;/p&gt;

&lt;p&gt;Вместе с полем &lt;code&gt;type&lt;/code&gt;, поле &lt;code&gt;key&lt;/code&gt; используется во время реконсилиации для определения того, можно ли переиспользовать результат файбера.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;child&lt;/code&gt; и &lt;code&gt;sibling&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Эти два поля ссылаются на другие файберы и описывают древовидную структуру файбера.&lt;/p&gt;

&lt;p&gt;Поле &lt;code&gt;child&lt;/code&gt; (потомок) ссылается на файбер, соответствующий результату функции &lt;code&gt;render&lt;/code&gt; компонента. Например:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;здесь, &lt;code&gt;Child&lt;/code&gt; будет файбером-потомком для &lt;code&gt;Parent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Поле &lt;code&gt;sibling&lt;/code&gt; (элемент того же уровня) учитывает случай, когда &lt;code&gt;render&lt;/code&gt; возвращает несколько потомков:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child1&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child2&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Поле &lt;code&gt;child&lt;/code&gt; ссылается на первый файбер в односвязном списке потомков. В примере выше, &lt;code&gt;Child1&lt;/code&gt; является файбером-потомком для &lt;code&gt;Parent&lt;/code&gt;, а &lt;code&gt;Child2&lt;/code&gt; - одноуровневый элемент (&lt;code&gt;sibling&lt;/code&gt;) для &lt;code&gt;Child1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Возвращаясь к аналогии с функциями, файбер-потомок можно представлять как &lt;a href="https://en.wikipedia.org/wiki/Tail_call" rel="noopener noreferrer"&gt;хвостовую рекурсию&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;return&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Поле &lt;code&gt;return&lt;/code&gt; ссылается на файбер, к которому нужно вернуться после обработки текущего файбера. Концептуально, это тоже самое, что адрес возврата в стековом фрейме. Можно считать этот файбер родительским.&lt;/p&gt;

&lt;p&gt;Если у файбера есть несколько потомков, &lt;code&gt;return&lt;/code&gt; каждого потомка ссылается на родителя. В примере выше, для &lt;code&gt;Child1&lt;/code&gt; и &lt;code&gt;Child2&lt;/code&gt; &lt;code&gt;return&lt;/code&gt; будет ссылаться на &lt;code&gt;Parent&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;pendingProps&lt;/code&gt; и &lt;code&gt;memoizedProps&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Концептуально, пропсы (props) это аргументы функции. Файберу устанавливаются &lt;code&gt;pendingProps&lt;/code&gt; в начале выполнения, а &lt;code&gt;memoizedProps&lt;/code&gt; устанавливаются в конце.&lt;/p&gt;

&lt;p&gt;Когда входящие &lt;code&gt;pendingProps&lt;/code&gt; равны &lt;code&gt;memoizedProps&lt;/code&gt;, это сигнал к тому, что предыдущий результат выполнения файбера может быть переиспользован, чтобы избежать ненужную работу.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;pendingWorkPriority&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Число означающее приоритет работы соответсвующего файбера. В модуле ReactPriorityLevel перечислены разные уровни приоритетов и то, что они представляют.&lt;/p&gt;

&lt;p&gt;За исключением приоритета NoWork, равного нулю, большее число соответствует меньшему приоритету. Например, можно было бы использовать следующую функцию, чтобы проверить, что приоритет файбера выше или равен заданному:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;matchesPriority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fiber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pendingWorkPriority&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;fiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pendingWorkPriority&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Планировщик использует значение приоритета, чтобы найти следующий блок работы на выполнение. Этот алгоритм рассмотрим в следующих разделах.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;alternate&lt;/code&gt;, дублер
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;очистка файбера&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Очистить файбер означает отрисовать его результат на экране.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;незавершенный файбер&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Необработанный файбер. Концептуально, текущий фрейм стека.&lt;/p&gt;

&lt;p&gt;В любой момент времени у экземпляра компонента есть не более двух файберов: текущий, очищенный файбер и незавершенный файбер.&lt;/p&gt;

&lt;p&gt;Дублер (&lt;code&gt;alternate&lt;/code&gt;) данного файбера — незавершенный файбер, а дублер незавершенного файбера — данный файбер.&lt;/p&gt;

&lt;p&gt;Дублер файбера создается отложено с помощью функции &lt;code&gt;cloneFiber&lt;/code&gt;. Вместо того, чтобы постоянно создавать новый объект, &lt;code&gt;cloneFiber&lt;/code&gt; попытается переиспользовать дублер, если он есть, чтобы минимизировать выделение памяти.&lt;/p&gt;

&lt;p&gt;К дублерам стоит относиться как к деталям реализации, но они часто упоминаются в коде, поэтому полезно их тут обсудить.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;output&lt;/code&gt;, вывод
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;хост-компонент&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Хост-компонент — листовая вершина в дереве элементов приложения. Хост-компоненты специфичны для среды отрисовки (например, в браузере это &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt; и так далее). В JSX, они обозначаются с помощью тегов в нижнем регистре.&lt;/p&gt;

&lt;p&gt;Концептуально, вывод файбера аналогичен результирующему значению функции.&lt;/p&gt;

&lt;p&gt;Каждый файбер в итоге имеет вывод, но он создается только в листовых узлах &lt;strong&gt;хост-компонентами&lt;/strong&gt;. После получения вывода, он передается вверх по дереву.&lt;/p&gt;

&lt;p&gt;Вывод это то, что в итоге передается отрисовщику, чтобы он мог сбросить изменения в среду отрисовки. Отрисовщик определяет как вывод создается и обновляется.&lt;/p&gt;

&lt;h3&gt;
  
  
  Будущие разделы
&lt;/h3&gt;

&lt;p&gt;Это все, что есть на данный момент, но этот документ еще далек до завершения. Будущие секции будут описывать алгоритмы используемые на протяжении жизненного цикла обновления. Темы для обсуждения включают:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;как планировщик находит следующий блок работы на выполнение.&lt;/li&gt;
&lt;li&gt;как отслеживается приоритет и распространяется по дереву файберов.&lt;/li&gt;
&lt;li&gt;как планировщик узнает, когда приостановить и продолжить работу.&lt;/li&gt;
&lt;li&gt;как файберы очищаются и помечаются как выполненные.&lt;/li&gt;
&lt;li&gt;как работают побочные эффекты (как например методы жизненного цикла).&lt;/li&gt;
&lt;li&gt;что такое сопрограмма и как она может быть использована для реализации контекста и лейаута.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Видео по теме
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/aV1271hd9ew" rel="noopener noreferrer"&gt;What's Next for React (ReactNext 2016)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>fiber</category>
    </item>
    <item>
      <title>Когда нужен React.memo?</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Fri, 25 Nov 2022 06:33:14 +0000</pubDate>
      <link>https://forem.com/jennypollard/react-memo-pomnitie-mienia-4ke3</link>
      <guid>https://forem.com/jennypollard/react-memo-pomnitie-mienia-4ke3</guid>
      <description>&lt;p&gt;&lt;em&gt;Когда нужен React.memo?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Компонент обновляется (перерисовывается), когда меняется его состояние. Когда обновляется компонент, обновляются все его дочерние компоненты и рекурсивно дочерние компоненты дочерних компонентов.&lt;/p&gt;

&lt;p&gt;Компонент может иметь глубокую вложенность дочерних компонентов:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В примере выше, при обновлении компонента &lt;code&gt;App&lt;/code&gt; произойдет обновление всех вложенных компонентов: &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt; и &lt;code&gt;C&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Обновление всех дочерних компонентов может быть нежелательно - если у компонента не меняется состояние и пропсы, то и обновлять его не надо. Обновление компонента можно остановить с помощью &lt;code&gt;React.memo&lt;/code&gt; (мемо). Мемо создает элемент, который ссылается на мемоизируемый компонент и содержит функцию сравнения пропсов для этого компонента:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elementType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="na"&gt;$typeof&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REACT_MEMO_TYPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;elementType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;При обновлении компонентов, React распознает мемо и вызывает функцию &lt;code&gt;compare&lt;/code&gt; чтобы определить изменились ли пропсы, если нет — можно &lt;a href="https://github.com/facebook/react/blob/f284d9fafac3af79c6901b6b63305cbd161304cd/packages/react-reconciler/src/ReactFiberBeginWork.new.js#L561" rel="noopener noreferrer"&gt;пропустить обновление&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memoizedProps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Default to shallow comparison&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;compare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;compare&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shallowEqual&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;workInProgress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bailoutOnAlreadyFinishedWork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;workInProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderLanes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Возвращаясь к первому примеру, обернем компонент &lt;code&gt;A&lt;/code&gt; в мемо:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Теперь, при обновлении &lt;code&gt;App&lt;/code&gt;, компонент &lt;code&gt;A&lt;/code&gt; и его вложенные компоненты обновляться не будут, так как их пропсы не изменяются.&lt;/p&gt;

&lt;p&gt;Использование мемо даст результат, если:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;компонент перерисовывается (обновляется) часто с одними и теми же пропсами.&lt;/li&gt;
&lt;li&gt;обновление компонента дорогое, например, когда у компонента большая вложенность дочерних компонентов.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Credits: foto by Oskar Yildiz &lt;a href="https://unsplash.com/photos/gy08FXeM2L4" rel="noopener noreferrer"&gt;https://unsplash.com/photos/gy08FXeM2L4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactmemo</category>
      <category>optimization</category>
    </item>
    <item>
      <title>React: сфокусировать поле ввода по чекбоксу</title>
      <dc:creator>jennypollard</dc:creator>
      <pubDate>Thu, 10 Nov 2022 19:36:56 +0000</pubDate>
      <link>https://forem.com/jennypollard/react-sfokusirovat-polie-vvoda-po-chiekboksu-2cc5</link>
      <guid>https://forem.com/jennypollard/react-sfokusirovat-polie-vvoda-po-chiekboksu-2cc5</guid>
      <description>&lt;p&gt;&lt;em&gt;Как установить фокус на поле ввода (инпут) при изменении чекбокса?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Даны чекбокс &lt;code&gt;&amp;lt;input type="checkbox"&amp;gt;&lt;/code&gt; и поле ввода &lt;code&gt;&amp;lt;input type="text"&amp;gt;&lt;/code&gt;. Хочу фокусировать поле ввода, когда пользователь отмечает чекбокс — так пользователю будет понятно, что от него ожидается ввод текста, если чекбокс включён.&lt;br&gt;
Напишу компонент, который показывает чекбокс и поле ввода, значение для поля ввода сохраню с помощью хуков &lt;code&gt;useState&lt;/code&gt; и &lt;code&gt;useCallback&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInputChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Добавлю обработчик на изменение чекбокса: покажу алерт с новым значением. Обработчик события вызывается с объектом &lt;code&gt;event&lt;/code&gt;, в свойстве &lt;code&gt;target&lt;/code&gt; лежит элемент, который вызвал событие, в моем случае &lt;code&gt;event.target&lt;/code&gt; — чекбокс. Новое значение чекбокса можно получить из его свойства &lt;code&gt;checked&lt;/code&gt;: &lt;code&gt;event.target.checked&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInputChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Теперь, при изменении чекбокса, установлю фокус в поле ввода. У элементов, которые могут получать фокус ввода, есть метод &lt;code&gt;focus&lt;/code&gt;. Чтобы вызвать этот метод у поля ввода, его нужно найти - в этом поможет механизм ref-ов и хук &lt;code&gt;useRef&lt;/code&gt;.&lt;br&gt;
Создам ref и передам его пропсой полю ввода:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;React, после рендера элементов, поместит в &lt;code&gt;inputRef&lt;/code&gt; ссылку на поле ввода. У всех ref-ов есть свойство &lt;code&gt;current&lt;/code&gt;, в котором хранится значение ref-а. Воспользуюсь им, чтобы вызвать метод &lt;code&gt;focus&lt;/code&gt; у элемента, для этого в обработчик изменения чекбокса добавлю &lt;code&gt;inputRef.current.focus()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInputChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Иногда может оказаться, что решение с использованием ref-ов слишком сложное. Тогда можно попробовать найти нужный элемент с помощью DOM API — например, &lt;code&gt;document.querySelector&lt;/code&gt;. Чтобы найти элемент используя &lt;code&gt;querySelector&lt;/code&gt;, его нужно как-то идентифицировать, добавлю ему &lt;code&gt;id&lt;/code&gt;. Затем, в обработчике изменения чекбокса, заменю ref на вызов &lt;code&gt;document.querySelector&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInputChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Использовать &lt;code&gt;documenent.querySelector&lt;/code&gt; нежелательно:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;нет гарантии, что найдет нужный элемент — сколько еще может быть на странице элементов с таким же селектором? &lt;/li&gt;
&lt;li&gt;компонент перестанет работать в окружении, где нет &lt;code&gt;document&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;querySelector будет искать элемент по всему дереву, а React сохранит ссылку на элемент в ref-е при рендере, что быстрее.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Поэтому вариант с ref-ами более стабильный и предсказуемый.&lt;/p&gt;

</description>
      <category>react</category>
      <category>hooks</category>
      <category>useref</category>
    </item>
  </channel>
</rss>
