[Перевод] Хуки — это лучшее, что случилось с React

React — это самая популярная фронтенд-библиотека из экосистемы JavaScript. Она известна простотой использования и читабельностью кода, создаваемого с её применением. Это позволяет организациям самых разных масштабов успешно внедрять данную библиотеку. Но компоненты, основанные на классах, это громоздкие конструкции, с которыми непросто разобраться. Хуки позволяют работать с состоянием компонентов, с методами их жизненного цикла, с другими механизмами React без использования классов.

dkoyq_0n81lak1atkj7mixup4vm.jpeg

В этой статье мы поговорим о том, что такое React-хуки, о том, что отличает их от других механизмов библиотеки, и о том, почему они — это лучшее, что случилось с React.

О возникновении хуков React


Изначально в библиотеке React использовались, в основном, компоненты, основанные на классах. Применение таких компонентов может потребовать приложения чрезмерных усилий в ходе разработки, так как программисту постоянно приходится переключаться между классами, компонентами высшего порядка, свойствами рендеринга. А с появлением хуков React можно, решая те же задачи, что и раньше, не переключаясь между различными механизмами, просто пользоваться функциональными компонентами. Хуки значительно улучшили React из-за того, что с их помощью можно писать код, который получается проще, чем код, который писали раньше, но при этом позволяет быстрее и эффективнее реализовывать похожий функционал. А ещё можно, не пользуясь классами, работать с состоянием компонентов и с методами их жизненного цикла.

Вот примеры кода, иллюстрирующие использование компонентов, основанных на классах, и функциональных компонентов.

Компонент, основанный на классах:

import React, { Component } from 'react'
 
export default class Hello extends Component {
    render() {
        return(
            
            Hello World!             
        )     }


Этот компонент выводит в DOM элемент

с сообщением Hello World!.

А вот — код функционального компонента, решающего ту же задачу.

import React from 'react'
 
export default function Hello() {
    return (
        
            Hello World!         
    ) }


Сравнение этих двух примеров показывает, что код функционального компонента гораздо проще кода аналогичного компонента, основанного на классах. Для его использования не нужно создавать экземпляр класса, не нужно вызывать render(). Достаточно просто вызвать нужную функцию. Хуки React обладают многими достоинствами, они способны помочь программисту в решении множества задач. Одна из главнейших сильных сторон хуков заключается в том, что они упрощают работу с методами жизненного цикла компонентов React.

Да, обратите внимание на то, что хуки нельзя использовать в компонентах, основанных на классах.

Как хуки упрощают работу с методами жизненного цикла компонентов?


Среди методов жизненного цикла React-компонента можно отметить те, которые вызываются при его монтировании, обновлении и размонтировании.

  • Монтирование — это вставка элементов в DOM.
  • Обновление — это, как можно судить по названию, обновление элементов DOM.
  • Размонтирование — это удаление элементов из DOM.


Вот схема, на которой представлены различные методы жизненного цикла React-компонента.

Ug6TQezzXUBiqBg1kVN32fDX93zK4S5CS5SdIPzY


Методы жизненного цикла React-компонента

Изначально эти методы можно было использовать только при применении компонентов, основанных на классах. Это обычно было связано с необходимостью работать с кодом, который достаточно сложно писать и читать. Если же пользоваться функциональными компонентами и хуками — решение тех же задач упрощается.

Предположим, нам нужно загрузить данные с использованием метода жизненного цикла componentDidMount() в компоненте, основанном на классах:

import React, { Component } from 'react'
import Axios from 'axios'
 
export default class Hello extends Component {
 
    constructor(props) {
        super(props);
        this.state = { name: ""};
    }
 
    componentDidMount() {
        Axios.get('/api/user/name')
        .then(response => {
            this.setState({ name: response.data.name })
        })
    }
 
    render() {
        return (
            
                My name is {this.state.name}             
        )     } }


А теперь решим ту же задачу в функциональном компоненте, пользуясь хуками useState и useEffect:

import React, { useEffect, useState } from 'react'
import Axios from 'axios'
 
export default function Hello() {
 
    const [Name, setName] = useState("")
 
    useEffect(() => {
        Axios.get('/api/user/name')
        .then(response => {
            setName(response.data,name)
        })
    }, [])
 
    return (
        
            My name is {Name}         
    ) }


Этот код загружает нужные данные с использованием Axios API и выводит их в DOM. Хуки useEffect и useState позволяют писать более эффективный и компактный код, чем код, который пишут при использовании компонентов, основанных на классах. Такой код получается понятнее, с ним легче работать. При использовании методов жизненного цикла в компонентах, основанных на классах, приходится по-отдельности работать с методами componentDidMount(), componentDidUpdate(), componentWillUnmount(), а при использовании хуков можно просто сделать всё, что нужно, с помощью useEffect.

Хуки облегчили изучение React


Компоненты, основанные на классах, всегда были несколько громоздкими и непонятными конструкциями, особенно учитывая то, что их применение ведёт к тому, что механизмы управления состоянием компонента и многократного использования кода кажутся сложнее, чем они есть на самом деле. Это привело к тому, что многие новички избегали React, выбирая более «лёгкие» библиотеки и фреймворки. А с появлением хуков изучить React стало легче, чем прежде. Это стало одной из причин роста популярности React.

GkKQL1hfjMyVd1NiJo-2kqkqOwwqaHugw6sjCAlg


Вопросы о различных библиотеках и фреймворках на Stack Overflow

На этом графике виден постоянный рост интереса к React на Stack Overflow, продолжающийся уже много лет. Здесь же можно сравнить процент вопросов о React с процентом вопросов о других популярных JavaScript-инструментах. Этот график доказывает то, что разработчики стали чаще пользоваться библиотекой React после появления хуков.

О некоторых хуках и их предназначении


До появления хуков организация кода компонентов на основе методов жизненного цикла вынуждала разработчиков «разбрасывать» по разным компонентам код, направленный на реализацию схожей логики. Для решений этой и других мелких проблем в React были введены функциональные компоненты, что позволило упростить код и сделать его более гибким. Ещё одна задача, которую постоянно приходилось решать разработчикам с использованием не особенно удобных механизмов, заключалась в изменении состояния компонентов. Для решения этой задачи теперь используется хук useState.

▍Хук useState


Вероятно, useState — это самый распространённый React-хук. Он позволяет работать с переменными состояния в функциональных компонентах.

const loadingTuple = React.useState(true)
const loading = loadingTuple[0]
const setLoading = loadingTuple[1]
 
 
 
loading // true
setLoading(false)
loading // false


Здесь useState принимает единственный аргумент: исходное значение состояния. Он возвращает массив с переменной state и с функцией для обновления этого состояния. После этого у программиста есть всё, что нужно для работы с состоянием в функциональном компоненте.

Следующий хук, который мы рассмотрим, направлен на работу с методами жизненного цикла в функциональных компонентах. Он называется useEffect.

▍Хук useEffect


Хук useEffect помогает программисту выполнять побочные эффекты в функциональных компонентах. То есть — вызывать функции, которые нужно выполнить после обновления DOM. Он заменяет некоторые события, позволяя вызывать функцию при изменении одной или нескольких переменных. Он принимает два аргумента: функцию и необязательный массив. Эта функция определяет то, какой именно «побочный эффект» нужно выполнить, а в массиве указывают переменные, за изменениями которых нужно наблюдать.

▍Другие хуки


  • useContext: позволяет работать с контекстом — с механизмом, используемым для организации совместного доступа к данным без необходимости передачи свойств.
  • useRef: позволяет напрямую обращаться к DOM в функциональных компонентах. Обратите внимание на то, что useRef, в отличие от setState, не вызывает повторный рендеринг компонента.
  • useReducer: хранит текущее значение состояния. Его можно сравнить с Redux.
  • useMemo: используется для возврата мемоизированного значения. Может применяться в случаях, когда нужно, чтобы функция возвратила бы кешированное значение.
  • useCallback: применяется в ситуациях, когда дочерние элементы компонента подвергаются постоянному повторному рендерингу. Он возвращает мемоизированную версию коллбэка, которая меняется лишь тогда, когда меняется одна из зависимостей.


Выше мы коснулись лишь некоторых наиболее часто используемых хуков React. Если вы хотите углубиться в их изучение — загляните сюда.

Итоги


Мы, при создании React-компонентов, пользовались классами из-за того, что в своё время для работы с состоянием или для реализации методов жизненного цикла нельзя было воспользоваться функциональными компонентами. Хуки React значительно упростили решение старых задач, дав нам возможность писать код, который отличается лучшей пригодностью к созданию нового функционала методом композиции, который получается гибче, чем прежде, который легче расширять. Многие компании используют React в роли своей основной фронтенд-библиотеки, что приводит к тому, что всё больше и больше разработчиков осваивают React.

Пользуетесь ли вы хуками React в своих проектах?

image-loader.svg

© Habrahabr.ru