{"componentChunkName":"component---src-templates-docs-js","path":"/docs/implementation-notes.html","result":{"data":{"markdownRemark":{"html":"<p>В этой главе собраны примеры из реализации <a href=\"/docs/codebase-overview.html#stack-reconciler\">согласователя Stack</a>. </p>\n<p>Они очень специфичны и требуют хорошего знания React API, а также ядра, рендереров и согласователя. Если вы не очень хорошо знакомы с архитектурой React, тогда изучите главу <a href=\"/docs/codebase-overview.html\">Архитектура кодовой базы</a>, а затем вернитесь к этой.</p>\n<p>Также предполагается, что вы понимаете <a href=\"/blog/2015/12/18/react-components-elements-and-instances.html\">разницу между компонентами, их экземплярами и элементами в React</a>.</p>\n<p>Согласователь Stack использовался в React 15 и более ранних версиях. Его код находится в каталоге <a href=\"https://github.com/facebook/react/tree/15-stable/src/renderers/shared/stack/reconciler\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/renderers/shared/stack/reconciler</a>.</p>\n<h3 id=\"video-building-react-from-scratch\"><a href=\"#video-building-react-from-scratch\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Видео: сборка React с нуля </h3>\n<p><a href=\"https://twitter.com/zpao\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Paul O’Shannessy</a> рассказал в своём докладе <a href=\"https://www.youtube.com/watch?v=_MAD4Oly9yg\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">как собрать React с нуля</a>, используя материал из этой главы.</p>\n<p>В его докладе и этой главе описаны упрощённые реализации, поэтому, ознакомившись с ними, вы сможете лучше понять, как работает реальная реализация.</p>\n<h3 id=\"overview\"><a href=\"#overview\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Введение </h3>\n<p>Согласователь не имеет открытого API. <a href=\"/docs/codebase-overview.html#renderers\">Рендереры</a>, такие как React DOM и React Native, используются, чтобы эффективно обновлять пользовательские UI-компоненты.</p>\n<h3 id=\"mounting-as-a-recursive-process\"><a href=\"#mounting-as-a-recursive-process\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Монтирование как рекурсивный процесс </h3>\n<p>Давайте рассмотрим, как компонент монтируется в первый раз.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> root <span class=\"token operator\">=</span> ReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">createRoot</span><span class=\"token punctuation\">(</span>rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nroot<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><code class=\"gatsby-code-text\">root.render</code> передаст <code class=\"gatsby-code-text\">&lt;App /></code> в согласователь. Запомните, что <code class=\"gatsby-code-text\">&lt;App /></code> — это React-элемент, т. е. описание того, что нужно отрендерить. Вы можете представлять его как просто объект.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { type: App, props: {} }</span></code></pre></div>\n<p>Согласователь будет проверять, чем является <code class=\"gatsby-code-text\">App</code>: классом или функцией.</p>\n<p>Если <code class=\"gatsby-code-text\">App</code> — функция, согласователь вызовет <code class=\"gatsby-code-text\">App(props)</code>, чтобы получить элемент, который нужно отрендерить.</p>\n<p>Если <code class=\"gatsby-code-text\">App</code> — класс, согласователь создаст экземпляр <code class=\"gatsby-code-text\">App</code> с помощью <code class=\"gatsby-code-text\">new App(props)</code>, вызовет метод жизненного цикла <code class=\"gatsby-code-text\">componentWillMount()</code>, а затем вызовет <code class=\"gatsby-code-text\">render()</code>, чтобы получить элемент, который нужно отрендерить.</p>\n<p>В любом случае, согласователь изучит элемент <code class=\"gatsby-code-text\">App</code>, чтобы узнать, что нужно отрендерить.</p>\n<p>Этот процесс рекурсивен. <code class=\"gatsby-code-text\">App</code> может рендерить <code class=\"gatsby-code-text\">&lt;Greeting /></code>, <code class=\"gatsby-code-text\">Greeting</code> — <code class=\"gatsby-code-text\">&lt;Button /></code>, и т. д. Согласователь будет рекурсивно погружаться в пользовательские компоненты, пока не узнает, что каждый компонент должен рендерить.</p>\n<p>Рассмотрим этот процесс с помощью псевдокода:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">type</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Подклассы React.Component имеют соответствующий флаг</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n    <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>isReactComponent<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Функция получает React-элемент (например, &lt;App />)</span>\n<span class=\"token comment\">// и возвращает узел, являющуюся вершиной DOM- или Native-дерева элементов.</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">var</span> props <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Мы будем вычислять необходимый элемент</span>\n  <span class=\"token comment\">// либо выполняя type как функцию,</span>\n  <span class=\"token comment\">// либо с помощью создания экземпляра и вызова метода render().</span>\n  <span class=\"token keyword\">var</span> renderedElement<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Компонент является классом</span>\n    <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">// Задать пропсы</span>\n    publicInstance<span class=\"token punctuation\">.</span>props <span class=\"token operator\">=</span> props<span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">// Если необходимо, вызвать метод жизненного цикла</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">.</span>componentWillMount<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">componentWillMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token comment\">// Получить необходимый элемент с помощью вызова render()</span>\n    renderedElement <span class=\"token operator\">=</span> publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Компонент является функцией</span>\n    renderedElement <span class=\"token operator\">=</span> <span class=\"token function\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Этот процесс может быть рекурсивным, потому что компонент может</span>\n  <span class=\"token comment\">// возвращать другой компонент.</span>\n  <span class=\"token keyword\">return</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span>renderedElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Примечание: эта реализация не завершена и выполняется бесконечно!</span>\n  <span class=\"token comment\">// Обрабатывает такие элементы как &lt;App /> и &lt;Button />.</span>\n  <span class=\"token comment\">// Пока не обрабатывает такие элементы как &lt;div /> и &lt;p />.</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">var</span> rootEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nrootEl<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<blockquote>\n<p><strong>Примечание:</strong></p>\n<p>Пример выше — псевдокод. Он не является реальной реализацией. А также этот код приводит к переполнению стека, потому что мы не описали, когда нужно остановить рекурсию.</p>\n</blockquote>\n<p>Рассмотрим основные идеи этого кода:</p>\n<ul>\n<li>React-элементы — просто объекты, описывающие тип компонента (например, <code class=\"gatsby-code-text\">App</code>) и его пропсы.</li>\n<li>Пользовательские компоненты могут быть как классами, так и функциями, но оба «рендерят» элементы.</li>\n<li>«Монтирование» — рекурсивный процесс, который создаёт DOM- или Native-дерево заданного React-элемента верхнего уровня (например, <code class=\"gatsby-code-text\">&lt;App /></code>).</li>\n</ul>\n<h3 id=\"mounting-host-elements\"><a href=\"#mounting-host-elements\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Монтирование базовых элементов </h3>\n<p>Процесс монтирования может стать бесполезным, если мы не отобразим результат на экран.</p>\n<p>В дополнение к пользовательским («составным») компонентам, React-элементы также могут быть представлены платформо-специфическими («базовыми») компонентами. Например, <code class=\"gatsby-code-text\">Button</code> может вернуть <code class=\"gatsby-code-text\">&lt;div /></code> из метода render().</p>\n<p>Если свойство <code class=\"gatsby-code-text\">type</code> имеет тип string, значит мы имеем дело с базовым элементом:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { type: 'div', props: {} }</span></code></pre></div>\n<p>Для базового элемента не существует пользовательского кода.</p>\n<p>Когда согласователь встречает базовый элемент, ответственность за монтирование возьмёт на себя рендерер. Например, React DOM может создать DOM-узел.</p>\n<p>Если элемент имеет потомков, согласователь рекурсивно монтирует их, следуя алгоритму выше. Потомки могут быть базовыми (например, <code class=\"gatsby-code-text\">&lt;div>&lt;hr />&lt;/div></code>), составными (например, <code class=\"gatsby-code-text\">&lt;div>&lt;Button />&lt;/div></code>) или обоих типов.</p>\n<p>DOM-узлы, созданные дочерними компонентами, будут добавлены к родительскому DOM-узлу, и рекурсивно будет собрана полная DOM-структура.</p>\n<blockquote>\n<p><strong>Примечание:</strong></p>\n<p>Согласователь не связан с DOM. Точный результат монтирования (иногда называемый «смонтированный образ») зависит от рендерера и может быть DOM-узлом (React DOM), строкой (React DOM Server) или числом (React Native).</p>\n</blockquote>\n<p>Если мы изменим код, чтобы он обрабатывал базовые элементы, то результат будет выглядеть вот так:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">type</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Подклассы React.Component имеют соответствующий флаг</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n    <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>isReactComponent<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Эта функция обрабатывает только составные элементы.</span>\n<span class=\"token comment\">// Например, &lt;App /> и &lt;Button />, но не &lt;div /></span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">mountComposite</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">var</span> props <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">var</span> renderedElement<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Компонент является классом</span>\n    <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">// Задать пропсы</span>\n    publicInstance<span class=\"token punctuation\">.</span>props <span class=\"token operator\">=</span> props<span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">// Если необходимо, вызвать метод жизненного цикла</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">.</span>componentWillMount<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">componentWillMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    renderedElement <span class=\"token operator\">=</span> publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Компонент является функцией</span>\n    renderedElement <span class=\"token operator\">=</span> <span class=\"token function\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Эта функция рекурсивна, но иногда достигает границ рекурсии, когда</span>\n  <span class=\"token comment\">// встречает базовый элемент (такой, как &lt;div />), вместо составного (такого, как &lt;App />):</span>\n  <span class=\"token keyword\">return</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span>renderedElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Эта функция обрабатывает только базовые элементы.</span>\n<span class=\"token comment\">// Например, &lt;div /> и &lt;p />, но не &lt;App />.</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">mountHost</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">var</span> props <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">var</span> children <span class=\"token operator\">=</span> props<span class=\"token punctuation\">.</span>children <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>children<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    children <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>children<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  children <span class=\"token operator\">=</span> children<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>Boolean<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Этот блок кода не следует размещать в согласователе.</span>\n  <span class=\"token comment\">// Каждый рендерер может инициализировать узлы по-своему.</span>\n  <span class=\"token comment\">// Например, React Native может создать представление для iOS или Android.</span>\n  <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      node<span class=\"token punctuation\">.</span><span class=\"token function\">setAttribute</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Монтировать потомков</span>\n  children<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">childElement</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Потомки могут быть как базовыми (&lt;div />), так и составными (&lt;Button />).</span>\n    <span class=\"token comment\">// Их мы тоже будем монтировать рекурсивно:</span>\n    <span class=\"token keyword\">var</span> childNode <span class=\"token operator\">=</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span>childElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Эта строка кода может отличаться</span>\n    <span class=\"token comment\">// в зависимости от рендерера</span>\n    node<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>childNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Вернуть DOM ноду в качестве результата.</span>\n  <span class=\"token comment\">// Здесь рекурсия заканчивается.</span>\n  <span class=\"token keyword\">return</span> node<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Пользовательский компонент</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">mountComposite</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'string'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Платформо-специфический компонент</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">mountHost</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">var</span> rootEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nrootEl<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Этот код работает, но всё ещё далёк от того, как согласователь реализован на самом деле. Отсутствует ключевая деталь — поддержка обновлений.</p>\n<h3 id=\"introducing-internal-instances\"><a href=\"#introducing-internal-instances\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Введение во внутренние экземпляры </h3>\n<p>Ключевая особенность React — ререндеринг всего без пересоздания DOM или сброса состояния:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">root<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Использовать уже существующий DOM:</span>\nroot<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Однако, наша реализация знает только как монтировать начальное дерево. Она не может обновлять его, потому что не содержит необходимой информации, например, экземпляры <code class=\"gatsby-code-text\">publicInstance</code>, или какой DOM-узел (<code class=\"gatsby-code-text\">node</code>) соответствует компоненту.</p>\n<p>Согласователь Stack решает эту проблему, сделав функцию <code class=\"gatsby-code-text\">mount()</code> методом класса. В этом решении есть недостатки, поэтому мы решили <a href=\"/docs/codebase-overview.html#fiber-reconciler\">переписать согласователь</a>. Однако, опишем, как он сейчас работает.</p>\n<p>Вместо разделения на функции <code class=\"gatsby-code-text\">mountHost</code> и <code class=\"gatsby-code-text\">mountComposite</code>, мы создадим два класса:</p>\n<p>Оба класса имеют конструктор, принимающий <code class=\"gatsby-code-text\">element</code>, а также имеют метод <code class=\"gatsby-code-text\">mount()</code>, который возвращает необходимый узел. Заменим вызывающую функцию <code class=\"gatsby-code-text\">mount()</code> на фабрику, которая будет создавать нужный класс:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Пользовательский компонент</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CompositeComponent</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'string'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Платформо-специфический компонент</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">DOMComponent</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>  \n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Для начала рассмотрим реализацию <code class=\"gatsby-code-text\">CompositeComponent</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CompositeComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement <span class=\"token operator\">=</span> element<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">getPublicInstance</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Для составных компонентов сделать экземпляр класса видимым.</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>publicInstance<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> element <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> props <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">var</span> publicInstance<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> renderedElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Компонент является классом</span>\n      publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// Задать пропсы</span>\n      publicInstance<span class=\"token punctuation\">.</span>props <span class=\"token operator\">=</span> props<span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// Если необходимо, вызвать метод жизненного цикла</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">.</span>componentWillMount<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">componentWillMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n      renderedElement <span class=\"token operator\">=</span> publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Компонент является функцией</span>\n      publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n      renderedElement <span class=\"token operator\">=</span> <span class=\"token function\">type</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Сохранить внешний экземпляр</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>publicInstance <span class=\"token operator\">=</span> publicInstance<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Получить внутренний экземпляр в соответствии с элементом.</span>\n    <span class=\"token comment\">// Это может быть DOMComponent для &lt;div /> или &lt;p />,</span>\n    <span class=\"token comment\">// и CompositeComponent для &lt;App /> или &lt;Button />:</span>\n    <span class=\"token keyword\">var</span> renderedComponent <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>renderedElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent <span class=\"token operator\">=</span> renderedComponent<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Монтировать полученный результат</span>\n    <span class=\"token keyword\">return</span> renderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Это не сильно отличается от предыдущей реализации <code class=\"gatsby-code-text\">mountComposite()</code>, однако теперь мы можем сохранять некоторую информацию, такую как <code class=\"gatsby-code-text\">this.currentElement</code>, <code class=\"gatsby-code-text\">this.renderedComponent</code> и <code class=\"gatsby-code-text\">this.publicInstance</code>, чтобы использовать во время обновлений.</p>\n<p>Заметьте, что экземпляр <code class=\"gatsby-code-text\">CompositeComponent</code>, это не то же самое, что экземпляр <code class=\"gatsby-code-text\">element.type</code>. <code class=\"gatsby-code-text\">CompositeComponent</code> — деталь реализации нашего согласователя, которая не может быть доступна пользователю. Пользовательский класс — это единственное, что мы читаем из <code class=\"gatsby-code-text\">element.type</code>, а <code class=\"gatsby-code-text\">CompositeComponent</code> создаёт его экземпляр.</p>\n<p>Чтобы избежать путаницы, мы будем называть экземпляры <code class=\"gatsby-code-text\">CompositeComponent</code> и <code class=\"gatsby-code-text\">DOMComponent</code> «внутренними экземплярами». Они существуют для того, чтобы мы могли сохранять в них некоторые долгоживущие данные. Только рендереры и согласователь знают об их существовании.</p>\n<p>В противоположность, мы будем называть экземпляры пользовательских классов «внешними экземплярами». Внешние экземпляры — это то, что вы видите как <code class=\"gatsby-code-text\">this</code> внутри <code class=\"gatsby-code-text\">render()</code> и других методов ваших компонентов.</p>\n<p>Функция <code class=\"gatsby-code-text\">mountHost()</code>, переименованная в метод <code class=\"gatsby-code-text\">mount()</code> класса <code class=\"gatsby-code-text\">DOMComponent</code>, также будет выглядеть знакомо:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">DOMComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement <span class=\"token operator\">=</span> element<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedChildren <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">getPublicInstance</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Для DOM-компонентов сделать DOM-узел видимым.</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> element <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> props <span class=\"token operator\">=</span> element<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> children <span class=\"token operator\">=</span> props<span class=\"token punctuation\">.</span>children <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>children<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      children <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>children<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Создать и сохранить узел</span>\n    <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Задать атрибуты</span>\n    Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        node<span class=\"token punctuation\">.</span><span class=\"token function\">setAttribute</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Создать и сохранить потомков.</span>\n    <span class=\"token comment\">// Каждый из них может быть либо DOMComponent, либо CompositeComponent,</span>\n    <span class=\"token comment\">// в зависимости от типа свойства type (строка или функция).</span>\n    <span class=\"token keyword\">var</span> renderedChildren <span class=\"token operator\">=</span> children<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>instantiateComponent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedChildren <span class=\"token operator\">=</span> renderedChildren<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Собрать DOM-узлы, которые возвращает метод mount.</span>\n    <span class=\"token keyword\">var</span> childNodes <span class=\"token operator\">=</span> renderedChildren<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">child</span> <span class=\"token operator\">=></span> child<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    childNodes<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">childNode</span> <span class=\"token operator\">=></span> node<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>childNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Вернуть DOM-узел в качестве результата</span>\n    <span class=\"token keyword\">return</span> node<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Основное отличие от метода <code class=\"gatsby-code-text\">mountHost()</code> в том, что теперь мы храним <code class=\"gatsby-code-text\">this.node</code> и <code class=\"gatsby-code-text\">this.renderedChildren</code> внутри DOMComponent. Мы будем использовать их в дальнейшем, чтобы не поломать структуру во время обновлений.</p>\n<p>В результате, каждый внутренний экземпляр (составной и базовый) имеет ссылку на свои внутренние экземпляры-потомки. Чтобы лучше представить себе этот процесс, создадим функциональный компонент <code class=\"gatsby-code-text\">&lt;App></code>, который рендерит класс-компонент <code class=\"gatsby-code-text\">&lt;Button></code>, который рендерит <code class=\"gatsby-code-text\">&lt;div></code>. Вот как может выглядеть дерево внутренних экземпляров:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token punctuation\">[</span>object CompositeComponent<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">currentElement</span><span class=\"token operator\">:</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">publicInstance</span><span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">renderedComponent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>object CompositeComponent<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">currentElement</span><span class=\"token operator\">:</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">publicInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>object Button<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">renderedComponent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>object DOMComponent<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">currentElement</span><span class=\"token operator\">:</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">node</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>object HTMLDivElement<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">renderedChildren</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Внутри DOM вы увидите только <code class=\"gatsby-code-text\">&lt;div></code>. Однако дерево внутренних экземпляров содержит как <code class=\"gatsby-code-text\">DOMComponent</code>, так и <code class=\"gatsby-code-text\">CompositeComponent</code>.</p>\n<p><code class=\"gatsby-code-text\">CompositeComponent</code> должен хранить:</p>\n<ul>\n<li>Текущий элемент.</li>\n<li>Внешний экземпляр, если свойство type в элементе является классом.</li>\n<li>Единственный внутренний экземпляр. Он может быть как <code class=\"gatsby-code-text\">DOMComponent</code>, так и <code class=\"gatsby-code-text\">CompositeComponent</code>.</li>\n</ul>\n<p><code class=\"gatsby-code-text\">DOMComponent</code> должен хранить:</p>\n<ul>\n<li>Текущий элемент.</li>\n<li>DOM ноду.</li>\n<li>Все внутренние экземпляры-потомки. Каждый из них может быть как <code class=\"gatsby-code-text\">DOMComponent</code>, так и <code class=\"gatsby-code-text\">CompositeComponent</code>.</li>\n</ul>\n<p>Если в более сложном приложении вам тяжело представить, как выглядит дерево внутренних экземпляров, <a href=\"https://github.com/facebook/react-devtools\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React DevTools</a> поможет вам в этом, выделяя базовые экземпляры серым цветом, а составные фиолетовым:</p>\n\n  <a class=\"gatsby-resp-image-link\" href=\"/static/d96fec10d250eace9756f09543bf5d58/00d43/implementation-notes-tree.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n  \n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block;  max-width: 840px; margin-left: auto; margin-right: auto;\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 61.904761904761905%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABXElEQVQoz5XSyW7bMBAAUP//r7VJGgdtFStWZJkiKXIorhJlroWbAEFyKOrBYG4PmG3HpoliKiZY3ZpyLrnU/45dykmAmMZp/7B/aVpGiVZzDPFyCTGmUurfLG/1Kw4h0FdCfo2yl5sMwUnHOqOFscrbpf6zj12t1XsPQjhnNyusdVJGgI1Sz2Gb52DMyjl3zgHAsize+5zzB661WmdnKVZFrDGMeYyX08ki5Aj1Si1nNCitCCHWWufcJ3yxGztO7Mj8HKJLNyzMe08R4RjECYvuMPetFvSVd2c5EI07eOlFd2DNWZ5GhbbL9nXmlBPnnDKqORL9E/Q/u8Pd43D/zH63rNmPDz/Q93v0jSts2SDpwJg2xrzjnDIeMR4xpVPTNO3heTwPjF8/ADjEFHPJIYXrvXIqKb6f7g1rq2EGqWTKNwx8xateaU/IkazzUkq9DW/aa6RFC7IT9Ub9B1SMslTHW6kcAAAAAElFTkSuQmCC'); background-size: cover; display: block;\">\n      <img class=\"gatsby-resp-image-image\" style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\" alt=\"React DevTools tree\" title=\"\" src=\"/static/d96fec10d250eace9756f09543bf5d58/1e088/implementation-notes-tree.png\" srcset=\"/static/d96fec10d250eace9756f09543bf5d58/65ed1/implementation-notes-tree.png 210w,\n/static/d96fec10d250eace9756f09543bf5d58/d10fb/implementation-notes-tree.png 420w,\n/static/d96fec10d250eace9756f09543bf5d58/1e088/implementation-notes-tree.png 840w,\n/static/d96fec10d250eace9756f09543bf5d58/00d43/implementation-notes-tree.png 1000w\" sizes=\"(max-width: 840px) 100vw, 840px\">\n    </span>\n  </span>\n  \n  </a>\n    \n<p>В завершении, создадим функцию, которая монтирует полученное дерево в узел-контейнер и возвращает внешний экземпляр.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element<span class=\"token punctuation\">,</span> containerNode</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Создать верхнеуровневый внутренний экземпляр</span>\n  <span class=\"token keyword\">var</span> rootComponent <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Монтировать верхнеуровневый компонент внутрь контейнера</span>\n  <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> rootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  containerNode<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Вернуть внешний экземпляр</span>\n  <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> rootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">getPublicInstance</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> publicInstance<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">var</span> rootEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"unmounting\"><a href=\"#unmounting\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Демонтирование </h3>\n<p>Теперь, когда у нас есть внутренние экземпляры, которые хранят своих потомков и DOM ноды, мы можем реализовать демонтирование. Для составного компонента демонтирование рекурсивно и вызывает метод жизненного цикла.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CompositeComponent</span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Если необходимо, вызвать метод жизненного цикла</span>\n    <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>publicInstance<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">.</span>componentWillUnmount<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Демонтировать единственный компонент</span>\n    <span class=\"token keyword\">var</span> renderedComponent <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent<span class=\"token punctuation\">;</span>\n    renderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Для <code class=\"gatsby-code-text\">DOMComponent</code> демонтировать каждого потомка:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">DOMComponent</span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Демонтировать всех потомков</span>\n    <span class=\"token keyword\">var</span> renderedChildren <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedChildren<span class=\"token punctuation\">;</span>\n    renderedChildren<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">child</span> <span class=\"token operator\">=></span> child<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>В действительности демонтирование DOM-компонентов также удаляет слушателей событий и очищает кэш, но опустим эти детали.</p>\n<p>Теперь добавим верхнеуровневую функцию <code class=\"gatsby-code-text\">unmountTree(containerNode)</code>, которая аналогична <code class=\"gatsby-code-text\">ReactDOM.unmountComponentAtNode()</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">unmountTree</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">containerNode</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Получить внутренний экземпляр из DOM ноды:</span>\n  <span class=\"token comment\">// (Пока не работает, нам нужно изменить mountTree(), чтобы хранить переменную.)</span>\n  <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> containerNode<span class=\"token punctuation\">.</span>firstChild<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">var</span> rootComponent <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span>_internalInstance<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Демонтировать дерево и очистить контейнер</span>\n  rootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  containerNode<span class=\"token punctuation\">.</span>innerHTML <span class=\"token operator\">=</span> <span class=\"token string\">''</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Чтобы это работало, нам нужно получить корневой внутренний экземпляр из DOM ноды. Мы изменим <code class=\"gatsby-code-text\">mountTree()</code>, добавив свойство <code class=\"gatsby-code-text\">_internalInstance</code> в корневую ноду. Также научим <code class=\"gatsby-code-text\">mountTree()</code> уничтожать уже существующее дерево, чтобы можно было вызывать этот метод несколько раз.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element<span class=\"token punctuation\">,</span> containerNode</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Уничтожить уже существующее дерево</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>containerNode<span class=\"token punctuation\">.</span>firstChild<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">unmountTree</span><span class=\"token punctuation\">(</span>containerNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Создать верхнеуровневый внутренний экземпляр</span>\n  <span class=\"token keyword\">var</span> rootComponent <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Монтировать верхнеуровневый компонент внутрь контейнера</span>\n  <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> rootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  containerNode<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Сохранить ссылку на внутренний экземпляр</span>\n  node<span class=\"token punctuation\">.</span>_internalInstance <span class=\"token operator\">=</span> rootComponent<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Вернуть внешний экземпляр</span>\n  <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> rootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">getPublicInstance</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> publicInstance<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Теперь вызов <code class=\"gatsby-code-text\">unmountTree()</code>, а также повторный вызов <code class=\"gatsby-code-text\">mountTree()</code> удалят старое дерево и запустят в компоненте метод жизненного цикла <code class=\"gatsby-code-text\">componentWillUnmount()</code>.</p>\n<h3 id=\"updating\"><a href=\"#updating\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Обновления </h3>\n<p>В предыдущей части мы реализовали демонтирование. Однако React не был бы так полезен, если бы после каждого изменения пропсов демонтировалось и монтировалось заново всё дерево.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">var</span> rootEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Использовать уже существующий DOM:</span>\n<span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Расширим наш внутренний экземпляр ещё одним методом. В дополнение к <code class=\"gatsby-code-text\">mount()</code> и <code class=\"gatsby-code-text\">unmount()</code>, в <code class=\"gatsby-code-text\">DOMComponent</code> и <code class=\"gatsby-code-text\">CompositeComponent</code> будет реализован новый метод <code class=\"gatsby-code-text\">receive(nextElement)</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CompositeComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">receive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nextElement</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">DOMComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">receive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nextElement</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Его задача — сделать всё необходимое, чтобы обновить компонент (со всеми потомками) в соответствии с <code class=\"gatsby-code-text\">nextElement</code>.</p>\n<p>Несмотря на то, что мы рекурсивно обновляем экземпляры <code class=\"gatsby-code-text\">DOMComponent</code> и <code class=\"gatsby-code-text\">CompositeComponent</code>, эту часть часто называют «diff-алгоритмом для виртуального DOM».</p>\n<h3 id=\"updating-composite-components\"><a href=\"#updating-composite-components\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Обновление составных компонентов </h3>\n<p>Когда составной компонент получает новый элемент, мы выполняем метод жизненного цикла <code class=\"gatsby-code-text\">componentWillUpdate()</code>.</p>\n<p>Затем мы заново отрендерим компонент с новыми пропсами и получим новый React-элемент:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CompositeComponent</span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">receive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nextElement</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> prevProps <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> publicInstance <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>publicInstance<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevRenderedComponent <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevRenderedElement <span class=\"token operator\">=</span> prevRenderedComponent<span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Обновить *свой* элемент</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement <span class=\"token operator\">=</span> nextElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> type <span class=\"token operator\">=</span> nextElement<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> nextProps <span class=\"token operator\">=</span> nextElement<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Вычислить новый результат render()</span>\n    <span class=\"token keyword\">var</span> nextRenderedElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">isClass</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Компонент является классом</span>\n      <span class=\"token comment\">// Если необходимо, вызвать метод жизненного цикла</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>publicInstance<span class=\"token punctuation\">.</span>componentWillUpdate<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">componentWillUpdate</span><span class=\"token punctuation\">(</span>nextProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n      <span class=\"token comment\">// Обновить пропсы</span>\n      publicInstance<span class=\"token punctuation\">.</span>props <span class=\"token operator\">=</span> nextProps<span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// Отрендерить снова</span>\n      nextRenderedElement <span class=\"token operator\">=</span> publicInstance<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> type <span class=\"token operator\">===</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Компонент является функцией</span>\n      nextRenderedElement <span class=\"token operator\">=</span> <span class=\"token function\">type</span><span class=\"token punctuation\">(</span>nextProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Далее, мы можем рассмотреть свойство <code class=\"gatsby-code-text\">type</code>. Если оно не изменилось с последнего рендеринга, то компонент ниже может быть обновлён.</p>\n<p>Например, если в первый раз результат был <code class=\"gatsby-code-text\">&lt;Button color=\"red\" /></code>, а во второй — <code class=\"gatsby-code-text\">&lt;Button color=\"blue\" /></code>, значит мы можем просто вызвать <code class=\"gatsby-code-text\">receive()</code> (с новым элементом в качестве параметра) у соответствующего внутреннего экземпляра:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">    <span class=\"token comment\">// ...</span>\n\n    <span class=\"token comment\">// Если свойство type не изменилось, то</span>\n    <span class=\"token comment\">// переиспользовать внутренний экземпляр и прекратить выполнение.</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>prevRenderedElement<span class=\"token punctuation\">.</span>type <span class=\"token operator\">===</span> nextRenderedElement<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      prevRenderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">receive</span><span class=\"token punctuation\">(</span>nextRenderedElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Однако, если свойство <code class=\"gatsby-code-text\">type</code> нового элемента отличается от предыдущего, то мы не можем обновить внутренний экземпляр. <code class=\"gatsby-code-text\">&lt;button></code> не может «превратиться» в <code class=\"gatsby-code-text\">&lt;input></code>.</p>\n<p>Вместо этого мы демонтируем существующий внутренний экземпляр и монтируем новый, который будет рендерить соответствующий элемент. Например, вот что происходит, когда компонент, который ранее рендерил <code class=\"gatsby-code-text\">&lt;button /></code>, рендерит <code class=\"gatsby-code-text\">&lt;input /></code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">    <span class=\"token comment\">// ...</span>\n\n    <span class=\"token comment\">// Если мы дошли до сюда, то нам нужно демонтировать предыдущий</span>\n    <span class=\"token comment\">// компонент, монтировать новый, и обменять их ноды.</span>\n\n    <span class=\"token comment\">// Найти старый узел, потому что его нужно заменить</span>\n    <span class=\"token keyword\">var</span> prevNode <span class=\"token operator\">=</span> prevRenderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Демонтировать старого потомка и монтировать нового</span>\n    prevRenderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> nextRenderedComponent <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>nextRenderedElement<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> nextNode <span class=\"token operator\">=</span> nextRenderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Обновить потомка</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent <span class=\"token operator\">=</span> nextRenderedComponent<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Заменить старого потомка на нового</span>\n    <span class=\"token comment\">// Заметка: этот код завязан на рендерере и,</span>\n    <span class=\"token comment\">// в идеале, должен находиться вне CompositeComponent:</span>\n    prevNode<span class=\"token punctuation\">.</span>parentNode<span class=\"token punctuation\">.</span><span class=\"token function\">replaceChild</span><span class=\"token punctuation\">(</span>nextNode<span class=\"token punctuation\">,</span> prevNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Подводя итог, когда составной компонент получает новый элемент, он может либо делегировать обновление внутреннему экземпляру, либо демонтировать старый компонент и монтировать новый.</p>\n<p>Существует ещё одна ситуация, когда компонент будет заново монтировать потомка вместо вызова <code class=\"gatsby-code-text\">receive()</code> — <code class=\"gatsby-code-text\">key</code> элемента изменился. Мы не будем обсуждать обработку <code class=\"gatsby-code-text\">key</code> в этой главе, потому что это добавит ещё больше сложности к и без того уже сложному материалу.</p>\n<p>Заметьте, что во внутренний экземпляр нам нужно добавить метод <code class=\"gatsby-code-text\">getHostNode()</code>, чтобы возможно было обнаружить платформо-специфичные ноды и заменить их во время обновления. Его реализация очевидна в обоих классах:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">CompositeComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Попросить внутренний экземпляр предоставить ноду.</span>\n    <span class=\"token comment\">// Этот вызов рекурсивно развернёт все компоненты.</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedComponent<span class=\"token punctuation\">.</span><span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">DOMComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>  \n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"updating-host-components\"><a href=\"#updating-host-components\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Обновление базовых компонентов </h3>\n<p>Хостовые компоненты, такие как <code class=\"gatsby-code-text\">DOMComponent</code>, обновляются по-другому. Когда они получают элемент, то им необходимо обновить платформо-специфический view. В случае с React DOM, это означает обновить DOM-атрибуты:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">DOMComponent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">receive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nextElement</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevElement <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevProps <span class=\"token operator\">=</span> prevElement<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> nextProps <span class=\"token operator\">=</span> nextElement<span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">;</span>    \n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentElement <span class=\"token operator\">=</span> nextElement<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Удалить старые атрибуты.</span>\n    Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>prevProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>nextProps<span class=\"token punctuation\">.</span><span class=\"token function\">hasOwnProperty</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        node<span class=\"token punctuation\">.</span><span class=\"token function\">removeAttribute</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">// Задать новые атрибуты.</span>\n    Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>nextProps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        node<span class=\"token punctuation\">.</span><span class=\"token function\">setAttribute</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">,</span> nextProps<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Затем хостовым компонентам необходимо обновить их потомков. В отличие от составных, они могут содержать более чем одного потомка.</p>\n<p>В этом упрощённом примере, мы используем массив внутренних экземпляров и проходим по каждому из них, обновляя либо заменяя внутренние экземпляры, в зависимости от того, соответствует ли полученный <code class=\"gatsby-code-text\">type</code> предыдущему. В реальности reconciler также берёт <code class=\"gatsby-code-text\">key</code> элементов и, в добавок к вставкам и удалениям элементов, отслеживает их перемещение, но мы опустим эту деталь.</p>\n<p>Соберём DOM-операции над потомками в список, чтобы мы смогли выполнить их обновление группой:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">    <span class=\"token comment\">// ...</span>\n\n    <span class=\"token comment\">// Массивы React-элементов</span>\n    <span class=\"token keyword\">var</span> prevChildren <span class=\"token operator\">=</span> prevProps<span class=\"token punctuation\">.</span>children <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>prevChildren<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      prevChildren <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>prevChildren<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">var</span> nextChildren <span class=\"token operator\">=</span> nextProps<span class=\"token punctuation\">.</span>children <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>nextChildren<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      nextChildren <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>nextChildren<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token comment\">// Массивы внутренних экземпляров</span>\n    <span class=\"token keyword\">var</span> prevRenderedChildren <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedChildren<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> nextRenderedChildren <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Проходя по потомкам, будем добавлять операции в массив.</span>\n    <span class=\"token keyword\">var</span> operationQueue <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Заметка: блок кода ниже очень упрощён! Он не обрабатывает </span>\n    <span class=\"token comment\">// переупорядочивание, передачу компонентов как пропсов, и потомков со свойством `key`.</span>\n    <span class=\"token comment\">// Он нужен только чтобы показать основы, а не детали.</span>\n\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> nextChildren<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Попытаться получить внутренний экземпляр</span>\n      <span class=\"token keyword\">var</span> prevChild <span class=\"token operator\">=</span> prevRenderedChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// Если не существует внутреннего экземпляра с этим индексом,</span>\n      <span class=\"token comment\">// то потомок будет добавлен в конец. Создать новый</span>\n      <span class=\"token comment\">// внутренний экземпляр, монтировать его и использовать его ноду.</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>prevChild<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">var</span> nextChild <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>nextChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> nextChild<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n        <span class=\"token comment\">// Записать, что нам нужно добавить ноду</span>\n        operationQueue<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">'ADD'</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        nextRenderedChildren<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>nextChild<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n\n      <span class=\"token comment\">// Мы можем обновлять экземпляры только если их элементы совпадают.</span>\n      <span class=\"token comment\">// Например, &lt;Button size=\"small\" /> может быть обновлён на</span>\n      <span class=\"token comment\">// &lt;Button size=\"large\" />, но не на &lt;App />.</span>\n      <span class=\"token keyword\">var</span> canUpdate <span class=\"token operator\">=</span> prevChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>type <span class=\"token operator\">===</span> nextChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// Если невозможно обновить существующий экземпляр, то мы должны</span>\n      <span class=\"token comment\">// демонтировать его и монтировать вместо него новый.</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>canUpdate<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">var</span> prevNode <span class=\"token operator\">=</span> prevChild<span class=\"token punctuation\">.</span><span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        prevChild<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n        <span class=\"token keyword\">var</span> nextChild <span class=\"token operator\">=</span> <span class=\"token function\">instantiateComponent</span><span class=\"token punctuation\">(</span>nextChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">var</span> nextNode <span class=\"token operator\">=</span> nextChild<span class=\"token punctuation\">.</span><span class=\"token function\">mount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n        <span class=\"token comment\">// Записать, что нам нужно поменять ноды</span>\n        operationQueue<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">'REPLACE'</span><span class=\"token punctuation\">,</span> prevNode<span class=\"token punctuation\">,</span> nextNode<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        nextRenderedChildren<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>nextChild<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n\n      <span class=\"token comment\">// Если возможно обновить существующий экземпляр, то передать</span>\n      <span class=\"token comment\">// новый элемент в receive() и позволить ему обновиться самостоятельно.</span>\n      prevChild<span class=\"token punctuation\">.</span><span class=\"token function\">receive</span><span class=\"token punctuation\">(</span>nextChildren<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      nextRenderedChildren<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>prevChild<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Наконец, демонтировать потомков, которых больше не существует:</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> j <span class=\"token operator\">=</span> nextChildren<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> prevChildren<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">var</span> prevChild <span class=\"token operator\">=</span> prevRenderedChildren<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">var</span> node <span class=\"token operator\">=</span> prevChild<span class=\"token punctuation\">.</span><span class=\"token function\">getHostNode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      prevChild<span class=\"token punctuation\">.</span><span class=\"token function\">unmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// Записать, что нам нужно удалить ноды      </span>\n      operationQueue<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">'REMOVE'</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Обновить список внутренних экземпляров</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>renderedChildren <span class=\"token operator\">=</span> nextRenderedChildren<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Последний шаг — выполним DOM-операции. Опять же, реальная реализация согласователя более сложная, потому что обрабатывает перемещения:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">    <span class=\"token comment\">// ...</span>\n\n    <span class=\"token comment\">// Обработать очередь операций</span>\n    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>operationQueue<span class=\"token punctuation\">.</span>length <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">var</span> operation <span class=\"token operator\">=</span> operationQueue<span class=\"token punctuation\">.</span><span class=\"token function\">shift</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>operation<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">case</span> <span class=\"token string\">'ADD'</span><span class=\"token operator\">:</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>operation<span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">case</span> <span class=\"token string\">'REPLACE'</span><span class=\"token operator\">:</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">.</span><span class=\"token function\">replaceChild</span><span class=\"token punctuation\">(</span>operation<span class=\"token punctuation\">.</span>nextNode<span class=\"token punctuation\">,</span> operation<span class=\"token punctuation\">.</span>prevNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">case</span> <span class=\"token string\">'REMOVE'</span><span class=\"token operator\">:</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>operation<span class=\"token punctuation\">.</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>И всё это нужно для обновления хостовых компонентов.</p>\n<h3 id=\"top-level-updates\"><a href=\"#top-level-updates\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Итоговая реализация обновлений </h3>\n<p>Сейчас, когда в <code class=\"gatsby-code-text\">CompositeComponent</code> и <code class=\"gatsby-code-text\">DOMComponent</code> реализован метод <code class=\"gatsby-code-text\">receive(nextElement)</code>, мы можем изменить вызывающую функцию <code class=\"gatsby-code-text\">mountTree()</code>, чтобы вызывать её, когда свойство <code class=\"gatsby-code-text\">type</code> в элементе не изменилось:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element<span class=\"token punctuation\">,</span> containerNode</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Проверить наличие дерева</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>containerNode<span class=\"token punctuation\">.</span>firstChild<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> prevNode <span class=\"token operator\">=</span> containerNode<span class=\"token punctuation\">.</span>firstChild<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevRootComponent <span class=\"token operator\">=</span> prevNode<span class=\"token punctuation\">.</span>_internalInstance<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">var</span> prevElement <span class=\"token operator\">=</span> prevRootComponent<span class=\"token punctuation\">.</span>currentElement<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Переиспользовать существующий корневой компонент, если это возможно</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>prevElement<span class=\"token punctuation\">.</span>type <span class=\"token operator\">===</span> element<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      prevRootComponent<span class=\"token punctuation\">.</span><span class=\"token function\">receive</span><span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Иначе, демонтировать существующее дерево</span>\n    <span class=\"token function\">unmountTree</span><span class=\"token punctuation\">(</span>containerNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Теперь вызов <code class=\"gatsby-code-text\">mountTree()</code> дважды с одним и тем же параметром ничего не разрушает.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">var</span> rootEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Переиспользовать существующий DOM:</span>\n<span class=\"token function\">mountTree</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> rootEl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Это и есть основа работы React изнутри.</p>\n<h3 id=\"what-we-left-out\"><a href=\"#what-we-left-out\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Что не было рассмотрено </h3>\n<p>Эта реализация упрощена по сравнению с реальной. Существует много важных вещей на которые мы не обратили внимание:</p>\n<ul>\n<li>Компоненты могут рендерить <code class=\"gatsby-code-text\">null</code>, а согласователь может обрабатывать массив из «пустых слотов».</li>\n<li>Согласователь также берёт <code class=\"gatsby-code-text\">key</code> элементов и использует их, чтобы установить связь между внутренними экземплярами и элементами в массиве. Основная сложность React связана именно с этой деталью.</li>\n<li>В дополнение к составным и хостовым компонентам, также существуют внутренние экземпляры для «текстовых» и «пустых». Они представляют текстовые ноды и «пустые слоты», которые вы получаете, когда рендерите <code class=\"gatsby-code-text\">null</code>.</li>\n<li>Рендереры используют <a href=\"/docs/codebase-overview.html#dynamic-injection\">инъекции</a>, чтобы прокинуть базовые компоненты в согласователь. Например, React Dom говорит reconciler-у, что нужно использовать <code class=\"gatsby-code-text\">ReactDOMComponent</code> в качестве внутреннего экземпляра.</li>\n<li>Логика обновления списка потомков вынесена в миксин <code class=\"gatsby-code-text\">ReactMultiChild</code>, который используется хостовым компонентами в React DOM и React Native.</li>\n<li>Согласователь также реализует поддержку <code class=\"gatsby-code-text\">setState()</code> в составных компонентах. Множество обновлений внутри события объединяются в единое обновление.</li>\n<li>Также согласователь берёт на себя ответственность за присоединение и отсоединение рефов для составных компонентов и хостовых нод.</li>\n<li>Методы жизненного цикла, которые вызываются по готовности DOM (такие, как <code class=\"gatsby-code-text\">componentDidMount()</code> и <code class=\"gatsby-code-text\">componentDidUpdate()</code>), собираются в «очередь обратных вызовов» и выполняются единым вызовом.</li>\n<li>React кладёт информацию о текущем обновлении в объект, называемый «транзакция». Транзакции полезны для отслеживания очереди из методов жизненного цикла, DOM предупреждений, и всего остального, что является «глобальным» для текущего обновления. Также транзакции гарантируют, что React «очищает всё» после обновлений. Например, класс транзакции, предоставляемый React DOM, после обновления восстановит выделение в инпуте.</li>\n</ul>\n<h3 id=\"jumping-into-the-code\"><a href=\"#jumping-into-the-code\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Погружение в код </h3>\n<ul>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/dom/client/ReactMount.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactMount</code></a> содержит методы <code class=\"gatsby-code-text\">mountTree()</code> и <code class=\"gatsby-code-text\">unmountTree()</code> из этой главы. Он заботится о монтировании и демонтировании компонентов. <a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/native/ReactNativeMount.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactNativeMount</code></a> — аналог из React Native.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/dom/shared/ReactDOMComponent.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactDOMComponent</code></a> — эквивалент <code class=\"gatsby-code-text\">DOMComponent</code> из этой главы. Он реализует хостовый компонент для React DOM рендерера. <a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/native/ReactNativeBaseComponent.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactNativeBaseComponent</code></a> — аналог из React Native.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactCompositeComponent</code></a> — эквивалент <code class=\"gatsby-code-text\">CompositeComponent</code> из этой главы. Он обрабатывает вызовы из пользовательских компонентов и хранит состояние.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/instantiateReactComponent.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">instantiateReactComponent</code></a> содержит switch для элемента, который выбирает необходимый внутренний экземпляр. Является эквивалентом <code class=\"gatsby-code-text\">instantiateComponent()</code> из этой главы.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactReconciler.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactReconciler</code></a> — обёртка над методами <code class=\"gatsby-code-text\">mountComponent()</code>, <code class=\"gatsby-code-text\">receiveComponent()</code> и <code class=\"gatsby-code-text\">unmountComponent()</code>. Вызывает соответствующую реализацию внутреннего экземпляра, а также включает некоторый общий код, который используют все реализации.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactChildReconciler.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactChildReconciler</code></a> реализует логику монтирования, обновления и демонтирования потомков, в соответствии со свойством <code class=\"gatsby-code-text\">key</code>.</li>\n<li><a href=\"https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactMultiChild.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ReactMultiChild</code></a> обрабатывает очередь операций для вставки, удаления и перемещения потомков независимо от используемого рендерера.</li>\n<li><code class=\"gatsby-code-text\">mount()</code>, <code class=\"gatsby-code-text\">receive()</code>, и <code class=\"gatsby-code-text\">unmount()</code> в репозитории React называются <code class=\"gatsby-code-text\">mountComponent()</code>, <code class=\"gatsby-code-text\">receiveComponent()</code>, и <code class=\"gatsby-code-text\">unmountComponent()</code> по историческим причинам, но, в качестве параметра, получают элемент.</li>\n<li>Свойства во внутренних экземплярах начинаются с нижнего подчёркивания, например, <code class=\"gatsby-code-text\">_currentElement</code>. Внутри репозитория являются открытыми и нигде не изменяются.</li>\n</ul>\n<h3 id=\"future-directions\"><a href=\"#future-directions\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Будущие изменения </h3>\n<p>Согласователь Stack имеет ограничения, такие как синхронность и невозможность прерывать выполнение или разделять задачу на подзадачи. Сейчас идёт работа над <a href=\"/docs/codebase-overview.html#fiber-reconciler\">new Fiber reconciler</a> с <a href=\"https://github.com/acdlite/react-fiber-architecture\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">совершенно другой архитектурой</a>. В будущем, мы собираемся поменять согласователь Stack на Fiber, но в настоящий момент он не является полноценным аналогом.</p>\n<h3 id=\"next-steps\"><a href=\"#next-steps\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Что дальше? </h3>\n<p><a href=\"/docs/design-principles.html\">В следующей главе</a> описаны принципы проектирования, которые мы используем в разработке React.</p>","frontmatter":{"title":"Детали реализации","next":"design-principles.html","prev":"codebase-overview.html"},"fields":{"path":"content/docs/implementation-notes.md","slug":"docs/implementation-notes.html"}}},"pageContext":{"slug":"docs/implementation-notes.html"}},"staticQueryHashes":[]}