Когда React был впервые выпущен, я проигнорировал его. Тоже довольно долго. Но потребительский спрос в конце концов заставил меня еще раз взглянуть на него, и я начал писать с его помощью некоторые веб-приложения. Чем даже больше и больше.

Однако мне всегда было немного странно с ним работать. У нас были классические компоненты и у нас были функциональные компоненты. Последние должны были быть быстрее и понятнее, чем первые, но: нет состояния. И, в конце концов, внутренне React все равно превратит их в классические компоненты.

Ситуация была настолько запутанной, что я даже посоветовал снова использовать функциональные компоненты. Я работал с клиентом, у которого было много разработчиков, которые не особо разбирались в Javascript, и им было очень трудно понять разницу между двумя способами написания компонентов. В конце концов, нам пришлось переписать множество компонентов, потому что оказалось, что для них требуется состояние или необходимо каким-то образом подключиться к жизненному циклу компонента, так что это был полный беспорядок. Лучшим решением было полностью перейти на классы компонентов, потому что всем было предельно ясно, как реализовать компоненты таким образом.

Когда были введены крючки, я был потрясен. Синтаксис был настолько простым и понятным для понимания, что я искренне спросил себя, почему никто не думал об этом решении все те годы, когда существовали функциональные компоненты. Я попробовал React 16.7 alpha, который оказался довольно стабильным. Я решил рискнуть и реализовать клиентский проект на основе этой альфа-версии и не был разочарован. Я почти не сталкивался с какими-либо ошибками, у меня в проекте есть 100% функциональные компоненты, и я смог без проблем обновить React до текущей версии 16.8.1.

Для меня разработка приложений с помощью React значительно улучшилась за счет хуков. Единственное улучшение в моей разработке, которое я испытал так же хорошо, как это, когда я начал использовать requireJS (кто-нибудь помнит это).

Использование состояния

Это довольно просто:

import React from 'react';

const MyComponent = () => {
    const [count, setCount] = React.useState(0);
    
    const addOne = () => setCount(count + 1);
    
    return <Button onClick={addOne}>You clicked me {count} times!</Button>
}

На мой взгляд, это легко понять. Я уже смешал свой личный вкус с использованием нативных хуков React: я не импортирую их отдельно. Часто можно встретить такие примеры:

import React, {useState} from 'react';

const MyComponent = () => {
    const [myVal, setMyVal] = useState(null);
    // ...
}

В большинстве случаев useState будет импортироваться отдельно, поэтому вы можете опустить React. перед ним. Я предпочитаю не импортировать ловушку отдельно, а использовать ее непосредственно из объекта React. Это избавит вас от хлопот по изменению оператора импорта, если вы решите теперь использовать собственный хук React.

Рекомендуется вызывать useState() для каждого необходимого значения состояния. Но вы также можете безопасно хранить там целые объекты. Просто помните, что вы делаете копию объекта перед его изменением, а затем отправляете копию в функцию установки.

А как насчет методов жизненного цикла?

Обновление хуков сокращает жизненный цикл в основном до двух вещей: componentDidMount и componentWillUnmount. Способ написания этого все еще немного ... ну:

import React from 'react';

const MyComponent = () => {
    React.useEffect(() => {
        console.log('I have been mounted!');
        
        return () => {
            console.log('I have been unmounted');
        };
    });
};

Это работает так: вы вызываете React.useEffect() внутри своего компонента и передаете ему функцию обратного вызова. Эта функция будет вызываться после монтирования компонента. Если вы хотите что-то сделать, когда компонент отключится, ваш первый обратный вызов должен вернуть второй обратный вызов. Этот второй обратный вызов в конечном итоге вызывается перед размонтированием. Уф. Мне этот узор не очень нравится, но что ж - привыкнешь.

Пользовательские крючки

В этом и заключается настоящая сила крючков реакции. Крючки - это просто функции. Вы можете создать свой собственный! Я использую это в значительной степени и абстрагировался от использования redux в своих проектах:

import React from 'react';
import {useArticle} from './customHooks';
import LoadGuard from './LoadGuard';

const ArticleDisplay = ({id}) => {
    const [article, articleStatus] = useArticle(id);
    
    return (
        <LoadGuard status={articleStatus}>
            {() => (
                <div>
                    <h1>{article.headline}</h1>
                    {article.body.map(paragraph => <p>{paragraph}</p>)}
                </div>
            )}
        </LoadGuard>
    );
};

Для меня это работает невероятно хорошо: ловушка в конечном итоге возвращает объект article. Поскольку он запрашивается по сети в первый раз, когда я запрашиваю его, он может быть недоступен изначально. Здесь в игру вступает компонент LoadGuard: он проверяет статус загрузки статьи и отображает заполнитель загрузки до тех пор, пока статус не изменится на «Готово» - тогда статья будет визуализирована.

Для редактирования данных крючок статьи предлагает еще больше возможностей:

const [article, articleStatus, saveArticle, deleteArticle] = useArticle(id);

Таким образом, вы получаете обработчики обновления и удаления, которые можно вызывать прямо из вашего компонента. Крючок позаботится обо всем. Да, и если вы не передадите id, будет возвращен новый пустой объект статьи, который можно редактировать и сохранять.

Я напишу больше об этой концепции и о том, как писать подобные перехватчики данных в отдельной статье.

Первоначально опубликовано на сайте parastudios.de 21 февраля 2019 г.
Следите за мной в твиттере, здесь.