HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p><strong><a>React Hooks</a></strong>- это долгожданные дополнения в React 16.8, с радостью встреченные сообществом React. Они являются полностью совместимыми с обычными подходами написания компонент.</p>
1 <p><strong><a>React Hooks</a></strong>- это долгожданные дополнения в React 16.8, с радостью встреченные сообществом React. Они являются полностью совместимыми с обычными подходами написания компонент.</p>
2 <p>Перед тем как рассматривать, что это такое, вспомним немного, как можно писать компоненты React.</p>
2 <p>Перед тем как рассматривать, что это такое, вспомним немного, как можно писать компоненты React.</p>
3 import React from 'react'; class Welcome extends React.Component { render() { return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;; } }<p>Данный компонент является тем, что называется stateless, - у него отсутствует, что называется state, - любые данные, которые свойственны конкретному компоненту, которые меняются по собственному желанию.</p>
3 import React from 'react'; class Welcome extends React.Component { render() { return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;; } }<p>Данный компонент является тем, что называется stateless, - у него отсутствует, что называется state, - любые данные, которые свойственны конкретному компоненту, которые меняются по собственному желанию.</p>
4 <p>Такие<strong>stateless-компоненты</strong>можно переписать в стрелочном виде:</p>
4 <p>Такие<strong>stateless-компоненты</strong>можно переписать в стрелочном виде:</p>
5 import React from 'react'; const Welcome = ({name}) =&gt; &lt;h1&gt;Hello, {name}&lt;/h1&gt;;<p>Как можно увидеть, писать такие<strong>stateless-компоненты</strong>в стрелочном виде - огромное удовольствие. Но что делать с компонентами, которые имеют состояние? Например, с таким:</p>
5 import React from 'react'; const Welcome = ({name}) =&gt; &lt;h1&gt;Hello, {name}&lt;/h1&gt;;<p>Как можно увидеть, писать такие<strong>stateless-компоненты</strong>в стрелочном виде - огромное удовольствие. Но что делать с компонентами, которые имеют состояние? Например, с таким:</p>
6 import React from 'react'; class Example extends React.Component { // Да, класс написан без наворотов babel - это для лучшего понимания ;) constructor(props) { super(props); this.state = { count: 0 }; } render() { const { count } = this.state; return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={ () =&gt; this.setState({count: count + 1}) }&gt; Click me &lt;/button&gt; &lt;/div&gt; ); } }<p>Обратите внимание, что для того, чтобы реализовать подобное состояние, необходимо: - проинициализировать начальное значение в конструкторе; - хранить этот count в state; - получать значение этого count в render; - и писать всё время this.setState(...), чтобы вызывать re-render при изменении state.</p>
6 import React from 'react'; class Example extends React.Component { // Да, класс написан без наворотов babel - это для лучшего понимания ;) constructor(props) { super(props); this.state = { count: 0 }; } render() { const { count } = this.state; return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={ () =&gt; this.setState({count: count + 1}) }&gt; Click me &lt;/button&gt; &lt;/div&gt; ); } }<p>Обратите внимание, что для того, чтобы реализовать подобное состояние, необходимо: - проинициализировать начальное значение в конструкторе; - хранить этот count в state; - получать значение этого count в render; - и писать всё время this.setState(...), чтобы вызывать re-render при изменении state.</p>
7 <p>И это ещё простой пример! В действительности код может быть куда сложнее, как минимум, с вынесенным методом изменения состояния.</p>
7 <p>И это ещё простой пример! В действительности код может быть куда сложнее, как минимум, с вынесенным методом изменения состояния.</p>
8 <p>Разберёмся, как этот компонент переписать с помощью<strong>React Hooks</strong>:</p>
8 <p>Разберёмся, как этот компонент переписать с помощью<strong>React Hooks</strong>:</p>
9 import React, { useState } from 'react'; const Example = () =&gt; { const [count, setCount] = useState(0); return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt; Click me &lt;/button&gt; &lt;/div&gt; ); }<p>Обратите внимание, компонент написан в виде стрелочной функции.</p>
9 import React, { useState } from 'react'; const Example = () =&gt; { const [count, setCount] = useState(0); return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt; Click me &lt;/button&gt; &lt;/div&gt; ); }<p>Обратите внимание, компонент написан в виде стрелочной функции.</p>
10 <h2>useState</h2>
10 <h2>useState</h2>
11 <p>Итак, useState:</p>
11 <p>Итак, useState:</p>
12 // Данная функция принимает начальное значение поля и возвращает специальный массив ... = useState(0);<p>Что возвращает:</p>
12 // Данная функция принимает начальное значение поля и возвращает специальный массив ... = useState(0);<p>Что возвращает:</p>
13 // useState возвращает массив из двух элементов - текущее состояние поля стейта // а ещё специальный метод - чтобы изменять состояние этого поля const [count, setCount] = useState(0);<p>Обратите внимание, что мы можем называть переменные для значения и метода, как хотим:</p>
13 // useState возвращает массив из двух элементов - текущее состояние поля стейта // а ещё специальный метод - чтобы изменять состояние этого поля const [count, setCount] = useState(0);<p>Обратите внимание, что мы можем называть переменные для значения и метода, как хотим:</p>
14 // Это всё корректно const [count, setCount] = useState(0); const [countValue, changeCount] = useState(0); const [c, updateCounter] = useState(0); const [userName, setUserName] = useState('Masha');<p>А дальше пользоваться этой переменной и методом можно вот таким образом:</p>
14 // Это всё корректно const [count, setCount] = useState(0); const [countValue, changeCount] = useState(0); const [c, updateCounter] = useState(0); const [userName, setUserName] = useState('Masha');<p>А дальше пользоваться этой переменной и методом можно вот таким образом:</p>
15 &lt;!-- Вот здесь просто вывели значение переменной --&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;!-- А вот здесь просто вызываем в обработчике --&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt;<p>А что будет, если мы напишем несколько хуков?</p>
15 &lt;!-- Вот здесь просто вывели значение переменной --&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;!-- А вот здесь просто вызываем в обработчике --&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt;<p>А что будет, если мы напишем несколько хуков?</p>
16 const [count, setCount] = useState(0); const [userName, setUserName] = useState('Masha');<p>Как ни странно,<strong>state</strong>не склеит эти два поля, и они будут изолированы. Как<strong>useState</strong>определит, что это два разных поля? Это просто - по порядку вызова. Ну, т. е. первый вызов useState вернёт значение и метод для “первого” поля, второй - значение и методы для “второго” и т. д.</p>
16 const [count, setCount] = useState(0); const [userName, setUserName] = useState('Masha');<p>Как ни странно,<strong>state</strong>не склеит эти два поля, и они будут изолированы. Как<strong>useState</strong>определит, что это два разных поля? Это просто - по порядку вызова. Ну, т. е. первый вызов useState вернёт значение и метод для “первого” поля, второй - значение и методы для “второго” и т. д.</p>
17 <p>Поэтому вводятся<strong>логичные практики</strong>: 1. Использовать хуки в корне компонента. 2. Не использовать хуки в циклах.</p>
17 <p>Поэтому вводятся<strong>логичные практики</strong>: 1. Использовать хуки в корне компонента. 2. Не использовать хуки в циклах.</p>
18 <p>Собственно, всё. Подведём промежуточные итоги: 1. Мы теперь можем писать компоненты со<strong>state</strong>и в стрелочном виде. 2. useState инициализирует поле state начальным значением. 3. useState берёт на себя обязанности по хранению поля state. 4. useState оборачивает вызов setState и предоставляет более удобный метод для изменения значения. Поэтому компонент обновится.</p>
18 <p>Собственно, всё. Подведём промежуточные итоги: 1. Мы теперь можем писать компоненты со<strong>state</strong>и в стрелочном виде. 2. useState инициализирует поле state начальным значением. 3. useState берёт на себя обязанности по хранению поля state. 4. useState оборачивает вызов setState и предоставляет более удобный метод для изменения значения. Поэтому компонент обновится.</p>
19 <p>Да и, разумеется, хуки нужно использовать только в функциональных компонентах.</p>
19 <p>Да и, разумеется, хуки нужно использовать только в функциональных компонентах.</p>
20 <h2>useEffect и другие</h2>
20 <h2>useEffect и другие</h2>
21 <p>Но и это не всё!</p>
21 <p>Но и это не всё!</p>
22 <p>Если мы хотим делать что-то дополнительное при обновлении компонента, то классический способ выглядел бы следующим образом:</p>
22 <p>Если мы хотим делать что-то дополнительное при обновлении компонента, то классический способ выглядел бы следующим образом:</p>
23 import React from 'react'; class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } // вызываем callback на начальном значении componentDidMount() { const { onNewValue } = this.props; onNewValue(this.state); } // вызываем callback при изменении значения componentDidupdate() { const { onNewValue } = this.props; onNewValue(this.state); } render() { const { count } = this.state; return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={ () =&gt; this.setState({count: count + 1}) }&gt; Click me &lt;/button&gt; &lt;/div&gt; ); } }<p>Обратите внимание, что помимо длинного кода, мы ещё и получили необходимость перегружать два метода: componentDidMount чтобы обновить данные на первом рендере и componentDidUpdate чтобы обновить данные при последующих рендерах.</p>
23 import React from 'react'; class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } // вызываем callback на начальном значении componentDidMount() { const { onNewValue } = this.props; onNewValue(this.state); } // вызываем callback при изменении значения componentDidupdate() { const { onNewValue } = this.props; onNewValue(this.state); } render() { const { count } = this.state; return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={ () =&gt; this.setState({count: count + 1}) }&gt; Click me &lt;/button&gt; &lt;/div&gt; ); } }<p>Обратите внимание, что помимо длинного кода, мы ещё и получили необходимость перегружать два метода: componentDidMount чтобы обновить данные на первом рендере и componentDidUpdate чтобы обновить данные при последующих рендерах.</p>
24 <p>Всё это можно объединить, используя хук useEffect:</p>
24 <p>Всё это можно объединить, используя хук useEffect:</p>
25 import React, { useState } from 'react'; const Example = ({onNewValue}) =&gt; { const [count, setCount] = useState(0); // Функция в аргументе вызовется на componentDidMount и componentDidUpdate useEffect(() =&gt; onNewValue(count)); return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt; Click me &lt;/button&gt; &lt;/div&gt; ); }<p>useEffect - это и есть способ задать componentDidMount и componentDidUpdate разом.</p>
25 import React, { useState } from 'react'; const Example = ({onNewValue}) =&gt; { const [count, setCount] = useState(0); // Функция в аргументе вызовется на componentDidMount и componentDidUpdate useEffect(() =&gt; onNewValue(count)); return ( &lt;div&gt; &lt;p&gt;You clicked {count} times&lt;/p&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt; Click me &lt;/button&gt; &lt;/div&gt; ); }<p>useEffect - это и есть способ задать componentDidMount и componentDidUpdate разом.</p>
26 <p>Помимо всего прочего - useRef, useReducer, useContext, useCallback и useMemo. Ну и оставим читателям возможность самостоятельно изучить, как писать собственные хуки.</p>
26 <p>Помимо всего прочего - useRef, useReducer, useContext, useCallback и useMemo. Ну и оставим читателям возможность самостоятельно изучить, как писать собственные хуки.</p>
27  
27