В предыдущих постах — часть 2 — я рассказывал о создании приложения React с бэкендом node.js с использованием фреймворка hapi.js.
В этом посте я опишу, как заставить нашего клиента общаться с нашим сервером, как его протестировать и настроить для разработки.
Цель такова:

Клиент реагирует, отображая имя, версию и статус серверной части.
Основой для этого поста является код с тегом «blog-post-2»:
Расширение серверной части
Работа API довольно проста, несколько новых методов и хранилище данных в памяти — myDataStore (его следует использовать только для тестирования).
Вызов работающего API (yarn start) должен возвращать имя и версию:
$ curl localhost:8080/api/version Hello from hapi-with-react-socketio tutorial version 1.0.1
Я также добавил несколько других вещей в бэкэнд-проект:
- автоматическое форматирование кода с использованием prettier и lint-staged
- изменен текст метаданных проекта на руководство по hapi-with-react-socketio
- добавлен набор тестов для новых методов API
Примечание о лучших практиках
В коде тестов есть одна строка, которая выглядит немного не так:
const DataStore = require('../../../server/api/index').data;
Поскольку API имеет состояние, тесты должны устанавливать и очищать это состояние во время выполнения. Это не то, что вы должны делать в рабочем коде. Это работает только здесь, потому что приложение работает в одном потоке, а зависимости (требования) кэшируются, поэтому и тесты, и сервер используют один и тот же экземпляр myDataStore. Если бы это был производственный код, я бы использовал какую-то инъекцию зависимостей и имитацию для управления этим состоянием (возможно, перемещенный в кэш в памяти, такой как Redis, или БД, например PostgreSQL).
Создание реактивного компонента
Чтобы отобразить информацию о версии, мы создадим компонент VersionInfo. Он попадет в наш API в componentDidMount и сохранит ответ в состоянии компонентов.
Это выглядит и работает отлично, но не очень хорошо проверяется. Тесты выявили одну проблему с этим кодом — что происходит, когда вызов API выполняется после размонтирования компонента (пользователь переходит на другую подстраницу)?
Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
Нам нужно как-то обработать этот случай — не вызывать setState для компонента, который был размонтирован.
Я последовал совету Facebook по поводу паттерна isMounted.
Есть несколько интересных реализаций «отменяемых промисов»:
Я создал что-то маленькое и простое:
Отменяемый код выглядит так:
Тестирование реактивных компонентов
Тестировать компоненты, использующие fetch, легко благодаря библиотеке fetch-mock.
Запуск клиента и сервера
На самом деле существует несколько способов запуска клиентского и серверного кода.
Во-первых, это производственный способ, который состоит из следующих шагов:
- Соберите клиент —
yarn build, который выполняет сборку всего проекта —yarn && cd client && yarn && yarn build - Запустите сервер —
yarn startкоторый обслуживает клиентские файлы в http://localhost:8080/app/
Это работает, но довольно медленно и раздражает вносить любые изменения в клиентский код, альтернативой является запуск клиента и сервера по отдельности. Это требует небольшого изменения в конфигурации, чтобы сообщить реагирующему клиенту, какой URL-адрес сервера. В client\package.json нам нужно добавить параметр proxy:
"proxy": "http://localhost:8080"
Далее нам нужно выполнить 2 команды в 2 окнах терминала
- Запустите сервер, выполнив сервер, используя
yarn startв корневом каталоге - Запустите клиент, выполнив
yarn startв каталогеclient, он должен открыть http://localhost:3000/

Состояние API
Исходный код также содержит API проверки работоспособности и клиентский компонент, который его отображает. Он очень похож на код, описанный в этом посте, и будет использоваться при развертывании kubernetes.
Исходный код
Следующий
В следующем посте я хочу рассказать о socket.io.