{"componentChunkName":"component---src-templates-docs-js","path":"/docs/lifting-state-up.html","result":{"data":{"markdownRemark":{"html":"<p>Часто несколько компонентов должны отражать одни и те же изменяющиеся данные. Мы рекомендуем поднимать общее состояние до ближайшего общего предка. Давайте посмотрим, как это работает.</p>\n<p>В этом разделе мы создадим калькулятор температуры, вычисляющий вскипит ли вода при заданной температуре.</p>\n<p>Мы начнём с компонента под названием <code class=\"gatsby-code-text\">BoilingVerdict</code>. Он принимает температуру по шкале Цельсия в качестве пропа <code class=\"gatsby-code-text\">celsius</code> и выводит, достаточна ли температура для кипения воды:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">BoilingVerdict</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>celsius <span class=\"token operator\">>=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Вода закипит.</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Вода не закипит.</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Затем мы создадим компонент <code class=\"gatsby-code-text\">Calculator</code>. Он рендерит <code class=\"gatsby-code-text\">&lt;input&gt;</code> для ввода температуры и сохраняет её значение в <code class=\"gatsby-code-text\">this.state.temperature</code>.</p>\n<p>Кроме того, он рендерит <code class=\"gatsby-code-text\">BoilingVerdict</code> для текущего значения поля ввода.</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Calculator</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span></span>    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>fieldset</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Введите температуру в градусах Цельсия:</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>temperature<span class=\"token punctuation\">}</span></span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">onChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">BoilingVerdict</span></span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">celsius</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">parseFloat</span><span class=\"token punctuation\">(</span>temperature<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>fieldset</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><a href=\"https://codepen.io/gaearon/pen/ZXeOBm?editors=0010\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><strong>Посмотреть на CodePen</strong></a></p>\n<h2 id=\"adding-a-second-input\"><a href=\"#adding-a-second-input\" 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>Добавление второго поля ввода </h2>\n<p>Добавим к полю ввода градусов Цельсия поле ввода по шкале Фаренгейта. Оба поля будут синхронизироваться.</p>\n<p>Мы можем начать с извлечения компонента <code class=\"gatsby-code-text\">TemperatureInput</code> из <code class=\"gatsby-code-text\">Calculator</code>. Добавим в него новый проп <code class=\"gatsby-code-text\">scale</code>, значением которого может быть либо <code class=\"gatsby-code-text\">&quot;c&quot;</code> или <code class=\"gatsby-code-text\">&quot;f&quot;</code>:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> scaleNames <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">  c<span class=\"token operator\">:</span> <span class=\"token string\">'Цельсия'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  f<span class=\"token operator\">:</span> <span class=\"token string\">'Фаренгейта'</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">TemperatureInput</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> scale <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>scale<span class=\"token punctuation\">;</span></span>    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>fieldset</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Введите температуру в градусах </span><span class=\"token punctuation\">{</span>scaleNames<span class=\"token punctuation\">[</span>scale<span class=\"token punctuation\">]</span><span class=\"token punctuation\">}</span><span class=\"token plain-text\">:</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>temperature<span class=\"token punctuation\">}</span></span>\n               <span class=\"token attr-name\">onChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>fieldset</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Теперь можем изменить <code class=\"gatsby-code-text\">Calculator</code> для рендера двух отдельных полей ввода температуры:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Calculator</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">TemperatureInput</span></span> <span class=\"token attr-name\">scale</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>c<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">TemperatureInput</span></span> <span class=\"token attr-name\">scale</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>f<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><a href=\"https://codepen.io/gaearon/pen/jGBryx?editors=0010\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><strong>Посмотреть на CodePen</strong></a></p>\n<p>Сейчас у нас есть два поля ввода, но когда вы вводите температуру в одно из них, другое поле не обновляется. Это противоречит нашему требованию — мы хотим их синхронизировать.</p>\n<p>Мы также не можем отображать <code class=\"gatsby-code-text\">BoilingVerdict</code> из <code class=\"gatsby-code-text\">Calculator</code>. Компонент <code class=\"gatsby-code-text\">Calculator</code> не знает текущую температуру, потому что она находится внутри <code class=\"gatsby-code-text\">TemperatureInput</code>.</p>\n<h2 id=\"writing-conversion-functions\"><a href=\"#writing-conversion-functions\" 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>Написание функций для конвертации температур </h2>\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\">toCelsius</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">fahrenheit</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>fahrenheit <span class=\"token operator\">-</span> <span class=\"token number\">32</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token number\">5</span> <span class=\"token operator\">/</span> <span class=\"token number\">9</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">toFahrenheit</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">celsius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>celsius <span class=\"token operator\">*</span> <span class=\"token number\">9</span> <span class=\"token operator\">/</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">32</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Эти две функции конвертируют числа. Мы напишем ещё одну функцию, которая принимает строку с температурой (<code class=\"gatsby-code-text\">temperature</code>) и функцию конвертации (<code class=\"gatsby-code-text\">convert</code>) в качестве аргументов, и возвращает строку. Мы будем использовать эту функцию для вычисления значения одного поля ввода на основе значения из другого поля ввода.</p>\n<p>Данная функция возвращает пустую строку при некорректном значении аргумента <code class=\"gatsby-code-text\">temperature</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\">tryConvert</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">temperature<span class=\"token punctuation\">,</span> convert</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> input <span class=\"token operator\">=</span> <span class=\"token function\">parseFloat</span><span class=\"token punctuation\">(</span>temperature<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>Number<span class=\"token punctuation\">.</span><span class=\"token function\">isNaN</span><span class=\"token punctuation\">(</span>input<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 string\">''</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">const</span> output <span class=\"token operator\">=</span> <span class=\"token function\">convert</span><span class=\"token punctuation\">(</span>input<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> rounded <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">round</span><span class=\"token punctuation\">(</span>output <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> rounded<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Например, вызов <code class=\"gatsby-code-text\">tryConvert(&#39;abc&#39;, toCelsius)</code> возвратит пустую строку, а вызов <code class=\"gatsby-code-text\">tryConvert(&#39;10.22&#39;, toFahrenheit)</code> — <code class=\"gatsby-code-text\">&#39;50.396&#39;</code>.</p>\n<h2 id=\"lifting-state-up\"><a href=\"#lifting-state-up\" 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>Поднятие состояния </h2>\n<p>В настоящее время оба компонента <code class=\"gatsby-code-text\">TemperatureInput</code> независимо хранят свои значения каждое в собственном локальном состоянии:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">TemperatureInput</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span></span>    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Однако мы хотим, чтобы эти два поля ввода синхронизировались друг с другом. Когда мы обновляем поле ввода градусов по Цельсию, поле ввода градусов по Фаренгейту должно отражать сконвертированную температуру и наоборот.</p>\n<p>В React совместное использование состояния достигается перемещением его до ближайшего предка компонентов, которым оно требуется. Это называется «подъём состояния». Мы удалим внутреннее состояние из <code class=\"gatsby-code-text\">TemperatureInput</code> и переместим его в <code class=\"gatsby-code-text\">Calculator</code>.</p>\n<p>Если <code class=\"gatsby-code-text\">Calculator</code> владеет общим состоянием, он становится «источником истины» текущей температуры для обоих полей ввода. Он может предоставить им значения, которые не противоречат друг другу. Поскольку пропсы обоих компонентов <code class=\"gatsby-code-text\">TemperatureInput</code> приходят из одного и того же родительского компонента <code class=\"gatsby-code-text\">Calculator</code>, два поля ввода будут всегда синхронизированы.</p>\n<p>Давайте шаг за шагом посмотрим, как это работает.</p>\n<p>Во-первых, мы заменим <code class=\"gatsby-code-text\">this.state.temperature</code> на <code class=\"gatsby-code-text\">this.props.temperature</code> в компоненте <code class=\"gatsby-code-text\">TemperatureInput</code>. Пока давайте представим, что <code class=\"gatsby-code-text\">this.props.temperature</code> уже существует, хотя нам нужно будет передать его из <code class=\"gatsby-code-text\">Calculator</code> в будущем:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Ранее было так: const temperature = this.state.temperature;</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span></span>    <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Мы знаем, что <a href=\"/docs/components-and-props.html#props-are-read-only\">пропсы доступны только для чтения</a>. Когда <code class=\"gatsby-code-text\">temperature</code> находилась во внутреннем состоянии, <code class=\"gatsby-code-text\">TemperatureInput</code> мог просто вызвать <code class=\"gatsby-code-text\">this.setState()</code> для изменения его значения. Однако теперь, когда <code class=\"gatsby-code-text\">temperature</code> находится в родительском компоненте в качестве пропа, <code class=\"gatsby-code-text\">TemperatureInput</code> не может контролировать его.</p>\n<p>В React это обычно решается путём создания «управляемого» компонента. Точно так же, как DOM-элемент <code class=\"gatsby-code-text\">&lt;input&gt;</code> принимает атрибуты <code class=\"gatsby-code-text\">value</code> и <code class=\"gatsby-code-text\">onChange</code>, так и пользовательский <code class=\"gatsby-code-text\">TemperatureInput</code> принимает оба пропса <code class=\"gatsby-code-text\">temperature</code> и <code class=\"gatsby-code-text\">onTemperatureChange</code> от своего родителя <code class=\"gatsby-code-text\">Calculator</code>.</p>\n<p>Теперь, когда <code class=\"gatsby-code-text\">TemperatureInput</code> хочет обновить свою температуру, он вызывает <code class=\"gatsby-code-text\">this.props.onTemperatureChange</code>:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Ранее было так: this.setState({temperature: e.target.value});</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span><span class=\"token function\">onTemperatureChange</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token comment\">// ...</span></code></pre></div>\n<blockquote>\n<p>Примечание:</p>\n<p>В пользовательских компонентах нет особого смысла в именах пропсов <code class=\"gatsby-code-text\">temperature</code> или <code class=\"gatsby-code-text\">onTemperatureChange</code>. Мы могли бы назвать их как-то иначе, например, <code class=\"gatsby-code-text\">value</code> и<code class=\"gatsby-code-text\">onChange</code>, т. к. подобные имена — распространённое соглашение.</p>\n</blockquote>\n<p>Пропсы <code class=\"gatsby-code-text\">onTemperatureChange</code> и <code class=\"gatsby-code-text\">temperature</code> будут предоставлены родительским компонентом <code class=\"gatsby-code-text\">Calculator</code>. Он будет обрабатывать изменения, модифицируя собственное внутреннее состояние, тем самым повторно отрендеривая оба поля ввода с новыми значениями. Вскоре мы рассмотрим новую реализацию <code class=\"gatsby-code-text\">Calculator</code>.</p>\n<p>Прежде чем изменить <code class=\"gatsby-code-text\">Calculator</code>, давайте вспомним, что поменялось в компоненте <code class=\"gatsby-code-text\">TemperatureInput</code>. Мы удалили из него внутреннее состояние, и вместо <code class=\"gatsby-code-text\">this.state.temperature</code> теперь используем <code class=\"gatsby-code-text\">this.props.temperature</code>. Вместо вызова <code class=\"gatsby-code-text\">this.setState()</code>, когда мы хотим изменить состояние, теперь вызываем <code class=\"gatsby-code-text\">this.props.onTemperatureChange()</code>, который получен от компонента <code class=\"gatsby-code-text\">Calculator</code>:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">TemperatureInput</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span><span class=\"token function\">onTemperatureChange</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span></span>    <span class=\"token keyword\">const</span> scale <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>scale<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>fieldset</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Введите градусы по шкале </span><span class=\"token punctuation\">{</span>scaleNames<span class=\"token punctuation\">[</span>scale<span class=\"token punctuation\">]</span><span class=\"token punctuation\">}</span><span class=\"token plain-text\">:</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>legend</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>temperature<span class=\"token punctuation\">}</span></span>\n               <span class=\"token attr-name\">onChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleChange<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>fieldset</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Теперь перейдём к компоненту <code class=\"gatsby-code-text\">Calculator</code>.</p>\n<p>Мы будем хранить текущие значения <code class=\"gatsby-code-text\">temperature</code> и <code class=\"gatsby-code-text\">scale</code> во внутреннем состоянии этого компонента. Это состояние, которое мы «подняли» от полей ввода, и теперь оно будет служить «источником истины» для них обоих. Это минимальное представление всех данных, про которое нам нужно знать для рендера обоих полей ввода.</p>\n<p>Например, если мы вводим 37 как значение поля ввода для температуры по шкале Цельсия, состояние компонента <code class=\"gatsby-code-text\">Calculator</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>\n  temperature<span class=\"token operator\">:</span> <span class=\"token string\">'37'</span><span class=\"token punctuation\">,</span>\n  scale<span class=\"token operator\">:</span> <span class=\"token string\">'c'</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Если позднее мы изменим поле для ввода градусов по шкале Фаренгейта на 212, состояние <code class=\"gatsby-code-text\">Calculator</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>\n  temperature<span class=\"token operator\">:</span> <span class=\"token string\">'212'</span><span class=\"token punctuation\">,</span>\n  scale<span class=\"token operator\">:</span> <span class=\"token string\">'f'</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Мы могли бы сохранить значения обоих полей ввода, но это оказалось бы ненужным. Достаточно сохранить значение последнего изменённого поля ввода и шкалу, которая это значение представляет. Затем мы можем вывести значение для другого поля ввода, основываясь только на текущих значениях <code class=\"gatsby-code-text\">temperature</code> и <code class=\"gatsby-code-text\">scale</code>.</p>\n<p>Поля ввода остаются синхронизированными, поскольку их значения вычисляются из одного и того же состояния:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Calculator</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleCelsiusChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleCelsiusChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleFahrenheitChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleFahrenheitChange</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>temperature<span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span> scale<span class=\"token operator\">:</span> <span class=\"token string\">'c'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleCelsiusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">temperature</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>scale<span class=\"token operator\">:</span> <span class=\"token string\">'c'</span><span class=\"token punctuation\">,</span> temperature<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleFahrenheitChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">temperature</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>scale<span class=\"token operator\">:</span> <span class=\"token string\">'f'</span><span class=\"token punctuation\">,</span> temperature<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> scale <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>scale<span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> temperature <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>temperature<span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> celsius <span class=\"token operator\">=</span> scale <span class=\"token operator\">===</span> <span class=\"token string\">'f'</span> <span class=\"token operator\">?</span> <span class=\"token function\">tryConvert</span><span class=\"token punctuation\">(</span>temperature<span class=\"token punctuation\">,</span> toCelsius<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> temperature<span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> fahrenheit <span class=\"token operator\">=</span> scale <span class=\"token operator\">===</span> <span class=\"token string\">'c'</span> <span class=\"token operator\">?</span> <span class=\"token function\">tryConvert</span><span class=\"token punctuation\">(</span>temperature<span class=\"token punctuation\">,</span> toFahrenheit<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> temperature<span class=\"token punctuation\">;</span></span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">TemperatureInput</span></span>\n          <span class=\"token attr-name\">scale</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>c<span class=\"token punctuation\">\"</span></span>\n<span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">temperature</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>celsius<span class=\"token punctuation\">}</span></span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">onTemperatureChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleCelsiusChange<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">TemperatureInput</span></span>\n          <span class=\"token attr-name\">scale</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>f<span class=\"token punctuation\">\"</span></span>\n<span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">temperature</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>fahrenheit<span class=\"token punctuation\">}</span></span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">onTemperatureChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleFahrenheitChange<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">BoilingVerdict</span></span>\n<span class=\"gatsby-highlight-code-line\">          <span class=\"token attr-name\">celsius</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">parseFloat</span><span class=\"token punctuation\">(</span>celsius<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><a href=\"https://codepen.io/gaearon/pen/WZpxpz?editors=0010\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><strong>Посмотреть на CodePen</strong></a></p>\n<p>Теперь, независимо от того, какое поле ввода вы редактируете, <code class=\"gatsby-code-text\">this.state.temperature</code> и <code class=\"gatsby-code-text\">this.state.scale</code> в <code class=\"gatsby-code-text\">Calculator</code> обновляются. Одно из полей ввода получает значение как есть, поэтому введённые пользователем данные сохраняются, а значение другого поля ввода всегда пересчитывается на их основе.</p>\n<p>Давайте посмотрим, что происходит, когда вы редактируете поле ввода:</p>\n<ul>\n<li>React вызывает функцию, указанную в <code class=\"gatsby-code-text\">onChange</code> на DOM-элементе <code class=\"gatsby-code-text\">&lt;input&gt;</code>. В нашем случае это метод <code class=\"gatsby-code-text\">handleChange()</code> компонента <code class=\"gatsby-code-text\">TemperatureInput</code>.</li>\n<li>Метод <code class=\"gatsby-code-text\">handleChange()</code> в компоненте <code class=\"gatsby-code-text\">TemperatureInput</code> вызывает <code class=\"gatsby-code-text\">this.props.onTemperatureChange()</code> с новым требуемым значением. Его пропсы, включая <code class=\"gatsby-code-text\">onTemperatureChange</code>, были предоставлены его родительским компонентом — <code class=\"gatsby-code-text\">Calculator</code>.</li>\n<li>Когда <code class=\"gatsby-code-text\">Calculator</code> рендерился ранее, он указал, что <code class=\"gatsby-code-text\">onTemperatureChange</code> в компоненте <code class=\"gatsby-code-text\">TemperatureInput</code> по шкале Цельсия — это метод <code class=\"gatsby-code-text\">handleCelsiusChange</code> в компоненте <code class=\"gatsby-code-text\">Calculator</code>, а <code class=\"gatsby-code-text\">onTemperatureChange</code> компонента <code class=\"gatsby-code-text\">TemperatureInput</code> по шкале Фаренгейта — это метод <code class=\"gatsby-code-text\">handleFahrenheitChange</code> в компоненте <code class=\"gatsby-code-text\">Calculator</code>. Поэтому один из этих двух методов <code class=\"gatsby-code-text\">Calculator</code> вызывается в зависимости от того, какое поле ввода редактируется.</li>\n<li>Внутри этих методов компонент <code class=\"gatsby-code-text\">Calculator</code> указывает React сделать повторный рендер себя, используя вызов <code class=\"gatsby-code-text\">this.setState()</code> со значением нового поля ввода и текущей шкалой.</li>\n<li>React вызывает метод <code class=\"gatsby-code-text\">render()</code> компонента<code class=\"gatsby-code-text\">Calculator</code>, чтобы узнать, как должен выглядеть UI. Значения обоих полей ввода пересчитываются исходя из текущей температуры и шкалы. В этом методе выполняется конвертация температуры.</li>\n<li>React вызывает методы <code class=\"gatsby-code-text\">render()</code> конкретных компонентов <code class=\"gatsby-code-text\">TemperatureInput</code> с их новыми пропсами, переданными компонентом <code class=\"gatsby-code-text\">Calculator</code>. Он узнает, как должен выглядеть UI.</li>\n<li>React вызывает метод <code class=\"gatsby-code-text\">render()</code> компонента <code class=\"gatsby-code-text\">Boiling Verdict</code>, передавая температуру в градусах Цельсия как проп.</li>\n<li>React DOM обновляет DOM, чтобы привести его в соответствие с нужными нам значениями в полях ввода. Отредактированное нами только что поле ввода получает его текущее значение, а другое поле ввода обновляется конвертированным значением температуры.</li>\n</ul>\n<p>Каждое обновление проходит через одни и те же шаги, поэтому поля ввода остаются синхронизированными.</p>\n<h2 id=\"lessons-learned\"><a href=\"#lessons-learned\" 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>Извлечённые уроки </h2>\n<p>Для любых изменяемых данных в React-приложении должен быть один «источник истины». Обычно состояние сначала добавляется к компоненту, которому оно требуется для рендера. Затем, если другие компоненты также нуждаются в нём, вы можете поднять его до ближайшего общего предка. Вместо того, чтобы пытаться синхронизировать состояние между различными компонентами, вы должны полагаться на <a href=\"/docs/state-and-lifecycle.html#the-data-flows-down\">однонаправленный поток данных</a>.</p>\n<p>Для подъёма состояния приходится писать больше «шаблонного» кода, чем при подходах с двусторонней привязкой данных, но мы получаем преимущество в виде меньших затрат на поиск и изолирование багов. Так как любое состояние «живёт» в каком-нибудь компоненте, и только этот компонент может его изменить, количество мест с возможными багами значительно уменьшается. Кроме того, вы можете реализовать любую пользовательскую логику для отклонения или преобразования данных, введённых пользователем.</p>\n<p>Если что-то может быть вычислено из пропсов или из состояния, то скорее всего оно не должно находиться в состоянии. Например, вместо сохранения <code class=\"gatsby-code-text\">celsiusValue</code> и <code class=\"gatsby-code-text\">fahrenheitValue</code>, мы сохраняем только последнюю введённую температуру (<code class=\"gatsby-code-text\">temperature</code>) и её шкалу (<code class=\"gatsby-code-text\">scale</code>). Значение другого поля ввода можно всегда вычислить из них в методе <code class=\"gatsby-code-text\">render()</code>. Это позволяет очистить или применить округление к значению другого поля, не теряя при этом точности значений, введённых пользователем.</p>\n<p>Когда вы видите, что в UI что-то отображается неправильно, то можете воспользоваться расширением <a href=\"https://github.com/facebook/react/tree/master/packages/react-devtools\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Developer Tools</a>. С помощью него можно проверить пропсы и перемещаться по дереву компонентов вверх до тех пор, пока не найдёте тот компонент, который отвечает за обновление состояния. Это позволяет отследить источник багов:</p>\n<img src=\"/ef94afc3447d75cdc245c77efb0d63be/react-devtools-state.gif\" alt=\"&#x41C;&#x43E;&#x43D;&#x438;&#x442;&#x43E;&#x440;&#x438;&#x43D;&#x433; &#x441;&#x43E;&#x441;&#x442;&#x43E;&#x44F;&#x43D;&#x438;&#x44F; &#x432; React DevTools\" max-width=\"100%\" height=\"100%\">","frontmatter":{"title":"Подъём состояния","next":"composition-vs-inheritance.html","prev":"forms.html"},"fields":{"path":"content/docs/lifting-state-up.md","slug":"docs/lifting-state-up.html"}}},"pageContext":{"slug":"docs/lifting-state-up.html"}},"staticQueryHashes":[]}