TL;DR:

Демонстрация блога React Spotify
Исходный код блога React Spotify

Предварительные требования

В этом проекте мы используем Node JS и npm, поэтому перед началом работы убедитесь, что они у вас установлены. Я также собираюсь быть высокоуровневым в React, CSS Grid или Flexbox, поэтому было бы хорошо ознакомиться с ними, прежде чем начать, и я не могу жить без ES7 async / await для работы с асинхронным кодом, таким как запросы AJAX. Если какой-либо из этих терминов звучит для вас странно, я не могу порекомендовать уроки от Wes Bos - самого умного и интересного канадца, которого я знаю!

Наконец, если вы действительно хотите иметь возможность нажимать кнопку воспроизведения и слушать музыку, вам потребуется подписка Premium Spotify. Если у вас его нет, то ничего страшного - вам просто нужно вручную открыть свои плейлисты в Spotify и открыть созданный нами новый.

Планируем

Я олдскульный, поэтому мне всегда нравится начинать с буквального листа бумаги, чтобы точно спланировать, как я хочу, чтобы что-то выглядело и что-то делало. У меня ужасный почерк, так что вот как выглядит моя статья:

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

Еще один важный шаг при планировании использования React - это составить список компонентов, которые вам понадобятся. Компоненты - это небольшие модули пользовательского интерфейса, которые можно комбинировать для создания общего пользовательского интерфейса. Не каждый элемент должен быть отдельным компонентом, но мы хотим получить самое главное. Исходя из моего рисунка (грубый каркас) нам понадобится около 7 компонентов:

Приложение / контейнер / оболочка

Пост избранного исполнителя

Автор

Меню выбора других сообщений

Контейнер Spotify

Компонент подключения (когда пользователь еще не вошел в систему)

Выбор плейлистов

Выбор правильных инструментов

Теперь, когда я знаю, чего хочу, следующий шаг - посмотреть, есть ли какие-либо существующие инструменты или библиотеки, которые дадут мне фору. Их несколько, поэтому большая часть работы сделана за нас!

  • Cosmic JS: отличная система управления контентом, которая предоставляет нашему приложению простой гибкий API с данными. Cosmic JS намного проще и легче, чем что-то вроде Wordpress, но дает нам возможность добавлять новые изображения художников позже без повторного развертывания приложения.
  • create-react-app: я специалист по React, но может быть сложно настроить всю конфигурацию для такого одностраничного приложения. У Facebook есть отличное репо и инструмент под названием create-react-app, который можно настроить.
  • CSS Grid, Flexbox: когда дело доходит до CSS, я не сторонник старой школы: Grid и Flexbox гораздо более предсказуемы, чем старая школа float: left. Мне нравится начинать новый проект с системами CSS, которые действительно имеют смысл
  • Material-UI: плоский дизайн и Material UI в моде, и, поскольку я не особо разбираюсь в презентациях, здорово иметь в наличии некоторые достойные компоненты дизайна, основанные на реакции.
  • Spotify API: Spotify имеет один из самых чистых и хорошо документированных REST API. И его еще проще использовать в интерфейсе javascript, используя отличную библиотеку-оболочку, вызываемую из JMPerez, которая называется spotify-web-api-js.

Начиная с create-react-app

Давайте начнем с клонирования приложения create-react-app. У них простые инструкции на репо. Если у вас версия npm 5.2 или выше, вы можете просто открыть терминал, перейти в новый каталог для проекта и ввести.

Я использую npm версии 4.2.0, поэтому мне нужно сначала установить инструмент командной строки create-response-app (инструмент CLI), а затем использовать инструмент CLI для создания приложения. Не забудьте также выполнить команду git init после ее завершения, чтобы вы могли сохранить свою работу.

Начните пример с npm start quick, чтобы убедиться, что все работает нормально. Если это выглядит так, тогда отличная работа! В противном случае у вас возникнут некоторые проблемы ... Мне не нравится файловая структура, которую дает нам create-react-app, поэтому мне нравится переделывать ее, чтобы поместить наши компоненты в их собственную подпапку под src. Таким образом, мы можем хранить вспомогательные файлы, которые не влияют на пользовательский интерфейс, непосредственно в src и отдельные компоненты в их собственной папке, чтобы их было легче просматривать.

Файловая структура по умолчанию create-react-app

Моя предпочтительная файловая структура

Если вы сделаете то же самое, не забудьте зайти в index.js и изменить ссылку на импорт для компонента App, чтобы вы могли найти index.js в подпапке новых компонентов.

Настройка структуры в

Давайте сначала создадим общую структуру с некоторыми фиктивными компонентами, а затем мы сможем детализировать по отдельности. Мы просто собираемся использовать этот компонент в качестве нашей оболочки верхнего уровня. Вытащите JSX-код и замените его следующим:

Код JSX / HTML только сообщает браузеру, что это за элементы, поэтому нам нужен CSS. Мы собираемся использовать CSS Grid для создания структуры, похожей на каркас. Медиа-запрос для экранов размером менее 800 пикселей помещает все в один столбец для мобильных устройств. Давайте пока просто скопируем этот код в App.css, и комментарии пояснят некоторые основные моменты.

Давай увидим это! Использование chrome devtools и выделение покажет вам сетку. Причина, по которой мы сделали 5 строк вместо 3, заключается в том, что мы хотим, чтобы проигрыватель Spotify мог дотянуться от верхнего до нижнего колонтитула, но слева мы хотим, чтобы избранный пост имел 2/3 вертикального пространства и другие посты только 1/3. Возможно, мы могли бы обойтись 4-мя рядами, но 5-й мне показался правильным.

В порядке! Давайте создадим первый реальный компонент отображения: обо всем по порядку - давайте возьмем несколько красивых компонентов из пользовательского интерфейса материала (он же Mui). Их страница начало работы проводит нас через это. Сначала нам нужно установить их пакет узлов.

Нам также необходимо добавить шрифт Roboto в наш index.html, чтобы все отображалось правильно.

В Mui есть отличный фоновый компонент под названием Paper, который похож на панели Bootstrap. Они также используют компонент Typography для заголовков и подзаголовков. Это выглядит классно, и я читал, что использование типографики упрощает применение их «тем» позже, если вы хотите изменить свой внешний вид.

Давайте продолжим и создадим два файла в нашей папке компонентов: FeaturedPost.js и FeaturedPost.css. Обычно я копирую App.js и App.css и просто заменяю «App» на «FeaturedPost», а затем редактирую, но ваш звонок. Вот как должны выглядеть эти файлы:

Если мы находимся в одном месте, приложение должно выглядеть примерно так:

Хорошо, это здорово. Но нет ничего скучнее статичного контента. Как насчет того, чтобы подключить к этой штуке какие-то данные? Данные - это контент, а это значит, что мы готовы установить Cosmic JS!

Получение динамического контента из Cosmic JS

Cosmic JS - это серверная система управления контентом, которая дает нам лучшее из разработки приложений и контента. Что касается контента, мы получаем все удобство интерфейса, подобного Wordpress, который маркетинговая команда или блоггер могут использовать, чтобы легко добавлять новые сообщения, авторов или все, что им угодно. На самом деле мне кажется, что этот Wordpress еще проще, потому что он чище и проще. Но на стороне разработки приложений мы получаем очень чистый, простой json-API, который мы можем передать в наше четкое приложение React (или любой другой фреймворк, который вам нравится). Нам не нужно иметь дело с php, плагинами и всем беспорядком, который навязывает нам Wordpress и раздувает веб-сайты. Ура!

Сначала создаем новую бесплатную учетную запись на Cosmic JS. Вам нужно будет подтвердить свой адрес электронной почты, или вы можете использовать GitHub для входа. Я рекомендую использовать GitHub, чтобы упростить развертывание в дальнейшем.

После того, как вы настроили свою учетную запись, вам необходимо создать новую корзину, в которую будут помещаться все данные контента для нашего приложения. Вы будете использовать уникальное имя для ведра (я использовал oldschoolshuffle). Выберите «Начать с нуля» и сохраните ведро.

Внутри сегмента данные организованы по объектам, типам объектов и файлам. Это очень легкая и гибкая система. Что это за каждый из них?

  • Типы объектов - это в основном схемы: они описывают класс вещей, которые вы, возможно, захотите использовать в своем приложении, и какие подробности об этой вещи важно знать. В нашем случае нам нужны сообщения, и нам нужны авторы, чтобы писать эти сообщения. Если вы делаете приложение о географии мира, у вас может быть тип объекта «Страна», или если вы делаете приложение для туристического агентства, у вас может быть тип объекта для полетов на самолетах или отелей. Важно то, что тип объекта имеет метаполя (свойства) для всего, что вы хотите знать об этом типе вещей.
  • Объекты - это любая дискретная вещь, на которую вы можете ссылаться в своем приложении. Сообщение о Кейси Масгрейвс - это объект типа объекта сообщения. Рейс AA2345 Остин-Бостон может быть объектом типа Flight в приложении туристического агентства.
  • Файлы - это мультимедийные или двоичные файлы (иногда называемые «статическими»), которые могут вам понадобиться. Обычно это будут изображения, но это может быть загружаемый контент, технические документы, mp3 или что-то еще.

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

Сначала мы настроим наш объектный тип для авторов, так как мы хотим, чтобы все знали, кто любит слушать музыку старой школы. На основе нашего каркаса автору нужно имя и изображение аватара, чтобы у нас было немного больше таланта. Нажмите «Добавить тип объекта» в меню слева, затем в разделе «Основные настройки» выберите «Автор» для имени в единственном числе и «Авторы» для имени во множественном числе.

Затем щелкните вкладку Шаблон метаполя. Каждый тип объекта автоматически получает заголовок и метаполе содержимого, поэтому нам не нужно добавлять метаполе заголовка, но нам нужно добавить метаполе для аватара. Нажмите на синий знак плюса, и вы увидите меню с различными типами метаполей. Мы хотим изображение, поэтому выберите его.

Помните, что мы еще не назначаем конкретного автора, поэтому не поддавайтесь искушению перетащить изображение, если вы не хотите установить значение по умолчанию. Что еще более важно, мы установили заголовок на avatarImage, чтобы мы могли назначать ему что-то позже. Мне нравится camelCaseToWriteThingsThatIllHaveToUseInMyCodeLater, но в этом случае вам не обязательно, потому что Cosmic JS автоматически назначит ключ, который мы будем использовать в коде.

По завершении нажмите кнопку «Сохранить тип объекта». Теперь мы можем создать двух наших конкретных авторов. Теперь вы должны увидеть новую папку авторов в левом меню. Нажмите на нее, и у вас должен появиться пустой раздел и кнопка «Добавить автора». Я рекомендую вам нажать эту кнопку.

Хорошо сделано! В заголовке укажите имя автора (я использовал Элвис Костелло). Вы также увидите, что наше метаполе avatarImage, которое мы создали в Object Type, перенесено, и теперь мы можем выбрать изображение, например трейлер старой школы RV, для использования в качестве аватара.

Когда мы закончим, нажмите кнопку Опубликовать, чтобы сохранить автора и закрыть экран.

Сделайте то же самое для второго автора, просто для удовольствия. Затем нам нужно создать тип объекта для наших сообщений, снова щелкнув Добавить тип объекта в меню. Поместите сообщение / сообщения для единственного / множественного числа и перейдите на вкладку Шаблон метаполя.

Мы добавляем два метаполя для сообщений: spotifyArtistId и author. Первый, spotifyArtistId, будет вводом обычного текста, и именно здесь мы будем хранить уникальный идентификатор, который Spotify использует для идентификации музыкальных исполнителей в их API.

Второе метаполе (автор) будет метаполем отношения одного объекта, что означает, что мы собираемся связать сообщения с ОДНИМ автором типа объекта, который мы создали ранее.

Убедитесь, что для метаполя автора вы выбрали «Ограничить поиск по типу объекта» и выберите «Авторы» в раскрывающемся меню. Для Поста не имеет смысла быть его автором. Как только это будет сделано, нажмите «Сохранить тип объекта», и мы вернемся к панели управления.

Совет профессионала! Если вы делали сообщения раньше авторов (прыгая с рук!), Вы можете вернуться и отредактировать свой объект сообщения, чтобы добавить автора Metafield. Выберите «Записи» в меню и щелкните значок шестеренки. Мне потребовалось время, чтобы понять это!

Хорошо, теперь нам просто нужно сделать несколько сообщений, а затем мы закончим с первоначальной настройкой контента! Нажмите Сообщения, затем Публикация в приложении, и давайте создадим 3. Используйте имя исполнителя для названия, отдайте ему дань уважения в разделе контента (вперед, я подожду) и выберите автора из раскрывающегося меню для каждого. Обратите внимание, что область содержимого поддерживает HTML, поэтому вы можете проявить там немного креатива. Вам также понадобится spotifyArtistId, который выглядит примерно так: 70kkdajctXSbqSMJbQO424. Вы можете найти идентификаторы своих любимых исполнителей здесь или просто использовать их:

  • Кейси Масгрейвс: 70kkdajctXSbqSMJbQO424
  • Райан Бингхэм: 31z9f9AyPawiq0qlBO1M3i
  • Тед Лео: 5hbH3dvtk49g07qpc1QwPe

МЫ НАКОНЕЦ ЗАВЕРШЕНЫ С КОНТЕНТОМ! Какая тренировка для мозга. Давайте вернемся к чему-нибудь простому, например к кодированию одностраничных приложений для мобильных устройств с использованием сторонних данных.

Подключение Cosmic JS Content

Во-первых: если вам неудобно работать с React, вам следует прекратить читать сейчас и пройти курс Уэса Боса React for Beginners, и вы буквально выйдете из себя как эксперт. Как и в случае с Grid CSS, я постараюсь оставаться на высшем уровне.

Звучит неплохо? Хорошо, давайте начнем с того, с чего начинаются все хорошие вещи в React - с нашего компонента верхнего уровня. В React все связано с состоянием (внутренними условиями в компоненте) и реквизитами (данными или функциями, которые передаются дочерним компонентам). Давайте добавим конструктор в.

Свойства в this.state - это все, что нам понадобится от Cosmic JS, чтобы сделать блог / дань уважения частью этой работы:

  • dataReceived начнет false и станет истинным после того, как мы получим данные из Cosmic JS. Это позволяет нам ждать рендеринга наших сообщений, пока мы не получим данные, необходимые для их правильного рендеринга.
  • posts - это массив, в котором мы будем хранить все сообщения, которые мы получаем от Cosmic JS.
  • Авторы - это массив, в котором мы будем хранить всех наших авторов из Cosmic JS.
  • FeaturedPostIndex - это целое число, которое мы будем использовать с массивом сообщений, чтобы определить, какое сообщение показывать в компоненте Featured Post. Остальные сообщения будут перечислены в компоненте «Другие сообщения».
  • otherPosts всегда будет подмножеством сообщений и не будет включать в себя сообщения, представленные в данный момент.

Теперь нам нужно подключить наше приложение React к нашему Cosmic JS API и получить данные, которые мы ввели обратно в CMS. Компоненты React действительно не должны выполнять слишком тяжелую работу, поэтому, чтобы они были модульными и удобочитаемыми, перейдите в папку src и добавьте новый файл с именем cosmicFunctions.js (он будет находиться вне каталога компонентов).

Cosmic JS предлагает действительно удобный модуль узла на npm, который упрощает получение необходимых данных без решения проблем CORS (cross-origin-request) или запросов ajax. Давайте сначала установим это с помощью npm.

Нам также нужно добавить файл .env с именем нашего Bucket (также называемого slug). Вы не хотите раскрывать эти конфиденциальные данные в своем коде, поэтому мы сохраняем их в переменной среды, которую вы не загружаете в свой общедоступный репозиторий. К счастью, приложение create-react-app упрощает эту задачу, поэтому вам просто нужно создать файл .env в корневом каталоге. Убедитесь, что он находится в корневом каталоге, а НЕ в вашем каталоге src, и начинается с точки. Нам также нужно начинать имя переменной с REACT_APP_, иначе приложение create-response-app проигнорирует его.

Если вы не знаете, что такое название Bucket, нажмите «Настройки» - «Основные настройки» на панели инструментов Cosmic JS, и вы увидите его во второй строке.

Теперь, когда мы настроены, мы импортируем модуль узла Cosmic JS в наш новый файл cosmicFunctions.js и добавим 2 функции getCosmicJsData и organizationCosmicJsDataByObjectType.

Давайте посмотрим на getCosmicJsData. Прежде чем мы определим функцию, вы заметите асинхронный экспорт. экспорт позволяет нам использовать эту функцию позже. async позволяет нам использовать асинхронные методы внутри функции, в нашем случае это запрос API ajax к Cosmic JS. Асинхронность означает, что мы отправляем API запрос, занимаемся своими делами, и когда мы получим ответ, наше приложение вернется к функции и задействует данные.

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

Давайте внимательнее посмотрим на 10-ю строку:

Вау, там много чего происходит. Логика такова: bucket.getObjects () - это асинхронный метод, который сообщает Cosmic JS, что нужно отправить нам полезную нагрузку всего, что у них есть. Поскольку у нас не так много данных, проще всего получить все из API сейчас (при первой загрузке страницы) и отсортировать их самостоятельно. Как это часто бывает с API, большая часть полезной нагрузки - это метаданные, которые нам не нужны. Итак, мы заключаем этот вызов в круглые скобки и просто берем его свойство objects, которое представляет собой массив всех сообщений и авторов, которые у нас есть.

Теперь у нас есть данные, которые нам нужны, в виде беспорядка всех наших типов объектов, но чтобы сохранить их в чистом виде в нашем состоянии, мы хотим быть более организованными. Вот почему мы передаем arrayOfAllObjectsInBucket в функцию organizationCosmicJsDataByObjectType. Он отображает массив и возвращает объект с ключами, основанными на различных типах объектов и массивах объектов этого типа. Мы могли бы просто искать сообщения и авторов, но этот способ более гибкий, и его не нужно будет менять позже, если мы решим переименовать сообщения в HomagesToGreatness или что-то в этом роде.

В любом случае, эти преобразованные данные выглядят так:

Видите, как хорошо это будет питаться в нашем государстве? Давай подключим! Компоненты React имеют встроенные методы жизненного цикла, с помощью которых мы можем сказать ему, что делать при загрузке, закрытии, повторной визуализации и т.д. не знаю, что это за DOM, вероятно, вам лучше просто оставить его сейчас), поэтому давайте добавим метод componentDidMount и поместим в него нашу функцию getCosmicJsData.

Несколько ключевых моментов в этом коде:

  • помните, что вам нужно импортировать нашу вспомогательную библиотеку cosmicFunctions для доступа к getCosmicJsData. Это также вверх по каталогу, поэтому вам нужно использовать ../
  • componentDidMount должен быть асинхронной функцией. Он содержит getCosmicJsData, который должен быть асинхронным, потому что он содержит bucket.getObjects (), который по своей сути является асинхронным.
  • Я стараюсь всегда заключать асинхронный код в блоки try / catch, поскольку никогда не знаешь, потерпят ли они неудачу.
  • Странный формат const {posts, авторы} =… - это деструктуризация ES6 и в основном то же самое, что и posts = someObject.posts. Разрушение отлично подходит для разрушения объектов.
  • В React вы НИКОГДА не можете назначать свойства this.state, кроме как в конструкторе. Это нарушает концепцию, называемую неизменяемость, но достаточно сказать, что это нарушает работу React. Вместо этого вы всегда используете this.setState, и React позаботится об этом за вас (спасибо React!)

Давайте также посмотрим на эту корявую строку:

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

На практике это просто тернарный оператор, который передает компонент JSX React, если this.state.dataReceived имеет значение true, или отображает пустую строку, если нет. Поскольку мы обновляем this.state.dataReceived в componentDidMount, React теперь знает, когда можно безопасно показывать FeaturedPost.

Последняя устрашающая вещь:

То же самое и с компонентом React, который мы создали ранее. Ему нужны данные в объекте Post, чтобы отобразить имя художника и почтение. this.state.posts - это массив объектов Post, которые мы получили от Cosmic JS.

this.state.featurePostIndex - это просто индекс массива, чтобы выбрать, какое сообщение в массиве нас интересует, например posts [0]. Итак, все, что мы делаем, это идентифицируем объект Post и передаем его FeaturedPost как свойство (props), называемое post. Таким образом, мы можем использовать данные в дочернем компоненте, даже если мы получили данные в родительском компоненте!

Давайте перейдем к отображению данных.

Выражая дань уважения Кейси Масгрейвс

Давайте сразу перейдем к коду и погрузимся в него. Мы собираемся изменить код, который мы написали ранее, чтобы извлекать данные из свойства post, которое мы только что передали.

Мы пока не собираемся использовать кнопку «Воспроизвести дискографию», но мы заменили исполнителя Cake на {this.props.post.title}, так что теперь мы получаем динамические заголовки постов / имена исполнителей. Контент мы также заменили динамическим контентом, но он более сложный, потому что контент Metafield из Cosmic JS - это HTML, а не просто текст.

React очень скептически относится к прямому внедрению HTML из внешних источников в ваше приложение, потому что это значительный риск для безопасности, но мы согласны с этим, потому что мы контролируем наши данные Cosmic JS и потому что это всего лишь пример приложения. Чтобы использовать внешний HTML, вы должны использовать свойство опасноSetInnerHTML в элементе div, а также передать ему объект с уникальным форматом, а не только HTML-код в виде обычной строки. Обычно они делают его громоздким, чтобы вы не сделали это по ошибке.

Мы также видим новый компонент, который также передает имя автора и изображение. То, что было дано вам вашим родителем, однажды вы передадите своему ребенку.

довольно прост, поэтому мы просто скопируем для этого код. Помните, что вам нужно будет создать файлы в каталоге компонентов для Author.js и Author.css. и не забудьте импортировать Author.js в начало FeaturedPost.js.

Запустите npm и посмотрите, как это выглядит. Надеюсь, что-то вроде этого?

Бум шака лака. Почти готово с содержанием! К сожалению, это, вероятно, самая сложная часть контента.

Давайте сделаем это из двух частей. Прежде чем мы перейдем к динамике, давайте создадим базовый тупой компонент, используя компонент панели расширения Material UI. Это означает создание файлов OtherPosts.js и OtherPosts.css в каталоге нашего компонента. Нам также нужно будет зайти в наш компонент и заменить текст заполнителя только что созданным фиктивным компонентом. Вот код:

Много кода, но ничего страшного. Панель расширения выглядит странно, но в основном это та же структура, что и

  • с вложенными
  • элементы и этикетка. Если все это собрано правильно, у вас должна быть чистая интерактивная панель, которая расширяется, чтобы показать наши фиктивные сообщения.

  • Давайте добавим туда данные. При обновлении мы передали реквизиты otherPosts в. Поскольку otherPosts представляет собой массив других сообщений, мы должны иметь возможность заменять наши фиктивные элементы путем сопоставления с массивом otherPosts и использования данных из каждого сообщения. Давай сделаем это сейчас:

Это не так уж и плохо. Использовать {postObject.title} для добавления названий постов очень просто. Единственная удивительная часть - это ключевое свойство, в которое мы включаем индекс массива, которого не было в нашем фиктивном компоненте. Причина в том, что React использует свойство key, чтобы различать похожие элементы с одним и тем же родителем (например,

  • elements), поэтому нам нужен уникальный ключ, который поможет React сохранить их правильность.

  • Это было не намного сложнее. Так почему я думаю, что это так сложно? Что ж, Уилбур, разве мы не хотим, чтобы ты мог щелкнуть другой пост и изменить его? Похоже, на какое сообщение было нажано внутреннее состояние. Подождите, это другой компонент ... это означает, что мы передаем состояние вверх по течению! Как, черт возьми, мы это делаем?
  • Вот вам ментальное джиу-джитсу - от этого состояния не избавиться. Помните this.state.featuredPostIndex, который живет в родительском (т.е.)? Вы пишете метод для изменения этого состояния и передаете этот метод.
  • Как это мета? Хотите чего-то более конкретного? Давайте запрограммируем это. Первый :

Здесь следует отметить несколько изменений:

Добавлен метод changeFeaturedPost: это метод, который мы передадим. затем можно вызвать метод, используя соответствующий индекс для сообщения. Это, в свою очередь, изменит state.featuredPostIndex в. Так как передается state.featuredPostIndex, то будет обновляться. Просто как пирог!

Passed allPosts to: понадобится массив всех сообщений, чтобы он мог определить индекс любого выбранного сообщения. Мы объясним это более подробно через минуту.

Передан метод changedFeaturedPost в: Передавая саму функцию, а не состояние, мы разрешаем ее вызывать. Не забудьте передать его как стрелочную функцию, а не просто {this.changedFeaturedPost}, иначе React запутается, и щелчок по сообщению вернет саму функцию, а не ее РЕЗУЛЬТАТ.

Теперь давайте обновим

Наконец-то резина отправляется в путь с помощью этого красивого метода handleClick! Вот что происходит:

Сначала мы должны передать метод handleClick в метод onClick для Post. Помните, что onClick - это прослушиватель событий, поэтому вы должны передать событие, даже если мы его не используем.

Этот метод вызывается при нажатии на сообщение и получает объект postObject сообщения, по которому щелкнули.

Чтобы вызвать метод changeFeaturedPost, который мы передали, нам действительно нужно просмотреть массив всех сообщений (вот почему мы передали его как props.allPosts) и вернуть ИНДЕКС, который соответствует сообщению, по которому только что щелкнули. В Javascript есть отличная функция array.findIndex, в которой мы можем определить, какие свойства объекта (в нашем случае мы ищем, и вернуть индекс.

Когда у нас есть этот индекс, мы просто вызываем с ним переданный нам метод changeFeaturedPost и вуаля - все остальное сделает React!

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

  • Прежде чем перейти к Spotify, хочу сказать одно: вы не единственный, кто ненавидит передачу функций между компонентами. Это приложение достаточно простое, чтобы сделать это таким образом, но для приложений с более чем дюжиной или около того компонентов я настоятельно рекомендую использовать Redux для управления вашим состоянием и свойствами. Идея в основном похожа на то, чтобы иметь библиотеку со всеми вашими свойствами и функциями в одном месте, а затем каждый компонент имеет библиотечную карту, чтобы получить любую функцию, которая ему нужна. Это требует большой настройки, но как только вы преодолеете это начальное препятствие, оно того стоит. Вы также можете попробовать React Context как еще одно решение проблемы.
  • Часть 2 - Атака интеграции Spotify
  • Теперь мы собираемся начать со второй части нашего приложения Old School Shuffle, которое представляет собой интеграцию со Spotify. Мы снова начинаем с мозгового штурма на листе бумаги, но на этот раз мы сосредоточимся в первую очередь на бэкенде, а в конце разберемся с интерфейсными компонентами. Что нам нужно делать со Spotify?
  • План Spotify

Для чего мне нужен API?

Получите доступ к Spotify пользователя

Получите их плейлисты

Получите треки для определенного плейлиста

Получите альбомы для определенного плейлиста

Получить треки для определенного альбома

Создать плейлист

Перемешать плейлист

Воспроизвести дискографию для конкретного исполнителя

Получите альбомы для исполнителя

Выполняется ли какая-либо из этих работ и доступна ли она для надстройки?

Да! Отличная библиотека-оболочка spotify-web-api-js от JMPerez!

Регистрация приложения в Spotify

  • Spotify имеет действительно универсальный API, который чрезвычайно хорошо документирован, и они помогают разработчикам использовать его с помощью своего Учебника по веб-API, но мы постараемся быстро приступить к работе. Сначала у вас должна быть учетная запись слушателя Spotify, которая, вероятно, у вас есть, если вы здесь. После этого вам нужно будет зайти в Личный кабинет, чтобы зарегистрироваться в качестве разработчика, а также зарегистрировать свое приложение, получив Client Id.
  • После входа в систему панель управления выглядит так:

  • Они помогут вам зарегистрировать приложение и получить идентификатор клиента. Если вы создаете некоммерческое приложение (например, приложение с открытым исходным кодом), оно бесплатное, но я думаю, что они берут плату за коммерческий доступ. Когда вы закончите, на панели управления появится идентификатор клиента.

  • Нам понадобится этот идентификатор клиента (я размыл свой), поэтому сохраните его в своем файле .env как REACT_APP_SPOTIFY_CLIENT_ID. Если вы не сделали этого во время настройки, нам также необходимо настроить «URI перенаправления» для нашего приложения. Нажмите кнопку «Изменить настройки» на панели инструментов, и вы увидите всплывающее окно, подобное этому:

  • Вам нужно будет добавить как вашу среду разработки (должно быть http: // localhost: 3000, если вы используете create-response-app), так и URL вашей производственной среды, когда мы вернемся к этому позже. Продолжайте и сохраните это в своем файле .env также как REACT_APP_SPOTIFY_DEVELOPMENT_REDIRECT_URI и REACT_APP_SPOTIFY_PRODUCTION_REDIRECT_URI. Вы можете проверить свой производственный URI на панели инструментов Cosmic JS.
  • Когда мы отправляем запрос на вход, Spotify будет использовать этот URI перенаправления, чтобы убедиться, что это действительно мы. Теперь ваш файл .env должен выглядеть примерно так:

Пока мы настраиваем вещи, давайте продолжим и установим spotify-web-api-js с npm, а также некоторые специальные вспомогательные функции Lodash, которые мы будем использовать.

Давайте также создадим файл spotifyFunctions.js в каталоге src (рядом с cosmicFunctions.js). Хотя в нем будет МНОГО кода, так что давайте пока просто импортируем наши библиотеки, а затем поговорим о том, как работает аутентификация Spotify.

Аутентификация

  • Авторизация - одна из тех вещей, которых опасается каждый веб-разработчик. Вы должны делать это постоянно, но, как правило, это минное поле с ошибками Cross-Origin (CORS), серверами OAuth2, Json Web Tokens (JWT), токенами рукопожатия и т. Д. токены обновления и HTTP-заголовки авторизации.
  • Все это выполнимо, но меня немного вырвет, особенно в небольшом демонстрационном приложении. Spotify поддерживает 3 разных метода аутентификации, но нам повезло, что они предлагают поток неявных грантов. Это не очень безопасно, но мы говорим о музыкальных плейлистах, а не о банковских счетах, и его можно использовать только в течение одного часа, поэтому вы можете создать слишком много проблем. Он идеально подходит для нас, потому что не требует серверного кода. Это удобно, потому что приложение create-react-app по умолчанию скрывает экспресс-маршруты. Вы можете настроить с его помощью прокси-сервер, но это кажется излишним только для этой аутентификации.
  • Вот диаграмма Spotify, показывающая, как работает неявное предоставление.

  • В отличие от OAuth / OAuth2 или JWT, которые требуют запросов ajax, Implicit Grant очень прост и работает на основе строки запроса, которая является способом передачи данных в URL-адрес веб-страницы. Фактически, мы делаем нашу кнопку входа в систему как внешнюю ссылку на URL-адрес авторизации Spotify, включая такие данные, как наш идентификатор клиента Spotify в строке запроса. Следуя по ссылке, пользователь фактически покидает нашу страницу и переходит на страницу, размещенную на Spotify, чтобы предоставить нашему приложению права доступа.
  • Если они согласны (или если они уже вошли в систему Spotify и предоставили нам разрешения ранее) Spotify проверит данные по приложению, которое мы зарегистрировали в базе данных, а затем они перенаправят пользователя обратно на нашу страницу, но включая строку запроса. с токеном авторизации. Все, что нам нужно сделать для доступа к API, - это включить этот токен (BQAHoHp… на снимке экрана) в наши запросы API. На самом деле нам даже не нужно создавать заголовки авторизации, потому что spotify-web-api-js сделает это за нас.

  • URL перед входом в систему

  • URL после входа в систему
  • Давайте попробуем это сейчас, создав 2 из 3 наших компонентов, связанных со Spotify:
  • это внешняя оболочка для нашего пользовательского интерфейса, связанного с Spotify.
  • это то, что мы будем показывать, когда пользователь еще не вошел в Spotify. В основном просто кнопка входа в систему.
  • позволяет пользователю выбирать из существующих списков воспроизведения и перемешивать их по альбомам. Мы займемся этим позже.
  • Нам также потребуется обновить, заменив нашу фиктивную «Spotify Player Here» на. И мы собираемся добавить несколько функций в spotifyFunctions.js. Вот код.

Мы не будем тратить много времени на эти компоненты: мы заменили фиктивный текст заполнителя Spotify на. указывает, вошли ли мы в систему, и если да, то какой у нас токен доступа из Spotify. Если state.loggedInToSpotify имеет значение false, мы показываем компонент (в основном просто кнопку входа в систему) или показываем заполнитель с токеном доступа.

  • также есть метод жизненного цикла componentDidMount, который проверяет при каждой визуализации, вошли ли мы в систему, используя функцию из нашей библиотеки spotifyFunctions.js. Вот и этот код.

Давайте начнем с входа в систему. RedirectUrlToSpotifyForLogin - это просто конкатенатор строк для создания URL-адреса со строкой запроса, чтобы сообщить Spotify, кто является нашим приложением и какие разрешения (Spotify называет их областями) мы хотим запросить у пользователя. Он также включает наш идентификатор клиента и URI перенаправления, которые мы зарегистрировали в Spotify. Вы можете видеть, что мы просто привязываем нашу кнопку входа к этому сгенерированному URL-адресу.

  • checkUrlForSpotifyAccessToken тоже очень прост. Он просто проверяет URL-адрес на строку запроса с параметром access_token. Это работает, потому что, когда мы впервые инициализируем наше приложение, наш URL-адрес будет http: // localhost: 3000, но после того, как мы войдем в систему, Spotify будет перенаправлять в наше приложение, используя наш URI перенаправления, но с прикрепленной авторизованной строкой запроса. Это будет выглядеть примерно так: http: // localhost: 3000 / # access_token = what. В этот момент будет повторно отрисован, увидеть токен доступа и отобразить код доступа в тексте вместо кнопки подключения к Spotify. Очень просто!
  • К вашему сведению, getHashParams - это просто универсальная вспомогательная функция для анализа строк запроса из URL-адреса.
    Теперь у нас есть все необходимое для входа в Spotify. Вот как это должно выглядеть.

  • Перед входом в систему

После входа в систему

  • Пользовательский интерфейс Spotify
  • Итак, теперь, когда мы вошли в систему, нам нужно добавить и подключить его. Пользователь должен иметь возможность выбирать из списка своих плейлистов и создавать новую версию в случайном порядке по альбомам. Если в вашем плейлисте есть ОДИНОЧНЫЕ СЛОВА (еретик!), Мы также включим возможность автоматического добавления для всего альбома. Вот как это должно выглядеть:

  • К настоящему времени вы уже опытны в коде фронтенда на React, поэтому я просто дам вам код сразу, вместо того, чтобы кормить с ложечки. Если у вас есть вопросы по этому поводу, вы можете задать их мне в комментариях. сильно зависит от Material UI, особенно их компонента Menu, и этот учебник может помочь вам разобраться в этом, если вы развернетесь. Не забывайте подключать его.

Вы заметите много ссылок на нашу вспомогательную библиотеку spotifyFunctions.js, поэтому она не будет отображаться, пока мы не займемся этой частью. Вот на чем я хочу сосредоточиться дальше.

Знакомьтесь, мистер Спот: ненадежный API

Вкратце, вот что мы хотим от API-части приложения:

  • План Spotify
  • Для чего мне нужен API?
  • Получите доступ к Spotify пользователя - Готово
  • Получите их плейлисты
  • Получите треки для определенного плейлиста
  • Получите альбомы для определенного плейлиста
  • Получить треки для определенного альбома
  • Создать плейлист
  • Перемешать плейлист
  • Воспроизвести дискографию для конкретного исполнителя
  • Получите альбомы для исполнителя

Вот весь код. Получите общее представление о том, насколько это соответствует нашим требованиям, но мы рассмотрим каждую функцию, поэтому не беспокойтесь, если вы не все понимаете. Заранее прошу прощения, что, наверное, выдержит небольшой рефакторинг.

Хорошо - возьмем сверху!

Мы рассмотрели импорт из немного ранее, но нам нужен реальный экземпляр библиотеки оболочки spotify-web-api-js, чтобы использовать его, поэтому мы создаем его здесь и называем spotifyApi.

Это те функции аутентификации, которые мы рассмотрели ранее. Здесь больше нечего сказать.

Когда у нас есть токен доступа, нам нужно передать его нашему экземпляру spotifyApi, и тогда нам не нужно беспокоиться о его запоминании для последующих вызовов функций. Мы должны экспортировать эту функцию, потому что она вызывается в componentDidMount в

Получив токен доступа, мы хотим получить массив пользовательских плейлистов, из которых они могут выбирать. Как и все функции, вызывающие сторонние API, это должна быть асинхронная функция. В нашем SpotifyApi есть встроенный метод getUserPlaylists, но Spotify предоставляет нам много информации о плейлисте, которая нам не нужна.

Чтобы уменьшить это, мы можем сопоставить массив объектов плейлистов, которые мы получаем от API, и вернуть массив более простых объектов только с идентификатором и именем каждого плейлиста, используя деструктуризацию ES6. Мы можем передать это в state.playlists и использовать его для заполнения нашего меню.

Обратите внимание, что у нас также есть обработчик ошибок, который возвращает сообщение «Не могу загрузить ваши плейлисты», если не может подключиться к API. Это также попадает в меню, поэтому пользователь получает несколько полезное сообщение вместо сбоя приложения, если есть проблемы с подключением.

После того, как пользователь выбирает список воспроизведения, нам нужно узнать, какие треки находятся в этом списке воспроизведения. Нам нужны название и идентификатор трека, название и идентификатор альбома, в котором он находится, номер трека в этом альбоме, а также имя и идентификатор исполнителя, исполняющего эту песню. Spotify также сохраняет URI, который мы можем просто ввести в браузер, чтобы получить трек, поэтому мы его тоже сохраним.

Это очень похоже на getSimplePlaylistTracks, но вместо получения playlistId мы передаем ему albumId, albumName и albumUri. Это полезно, когда пользователь хочет добавить дискографию, потому что мы можем прокручивать их списки воспроизведения, получать альбомы для каждого трека, а затем использовать это для получения всех других треков из того же альбома.

Обе функции выглядят очень похоже, но немного отличаются, потому что ответы Spotify API для альбомов структурированы немного иначе, чем их данные в плейлистах. Вероятно, есть умный способ преобразовать их в одну функцию - если у вас это получится, дайте мне знать!

Как мы уже говорили в предыдущем разделе, эта функция получает результат getSimplePlaylistTracks и создает массив идентификаторов альбомов из треков в этих плейлистах. Его можно передать в getSimpleAlbumTracks, если нам нужна полная дискография, или просто вернуть albumId, если нам просто нужно отсортировать плейлист по альбомам. Флаг returnSimpleArray позволяет нам решить, какой тип вывода нам нужен.

Обратите внимание, что мы сначала получаем массив albumIds, затем удаляем дубликаты из массива с помощью функции Lodash uniq, а затем перемешиваем его. Более эффективно сначала перемешать альбомы, прежде чем добавлять к ним треки.

Это просто общая вспомогательная функция для случайного перемешивания массивов.

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

Это непростой вопрос. По сути, мы берем большой массив треков в плейлисте и конвертируем его из связного массива в объект с меньшими массивами с тем же идентификатором albumId. Эти короткие массивы представляют собой альбомы, поэтому в каждом альбоме мы сортируем треки по их номерам в альбоме. Позже мы можем их рекомбинировать.

Вот пример того, как выглядит эффект convertPlaylistToObjectByProperty:

Прохладный. Вот быстрый:

Это отличная вспомогательная функция для сортировки и создания массива объектов на основе указанного свойства объектов внутри него, когда вы передаете его в качестве параметра в array.sort, как мы это делали в convertPlaylistToPbjectByProperty. Я беззастенчиво поднял это из Stack Overflow и должен поблагодарить Ege Ozcan!

Посмотрите на это заявление об экспорте! Посмотрите, насколько это читабельно! Эта функция вызывается с помощью кнопки «Воспроизвести сейчас», когда пользователь выбирает перемешивание списка воспроизведения по альбому БЕЗ добавления недостающих треков. Это асинхронная функция, и теперь мы действительно извлекаем выгоду из абстрагирования наших низкоуровневых операций.

Мы начинаем с получения состояния и извлечения имени и идентификатора списка воспроизведения, выбранного пользователем. Оттуда мы:

  • получить массив треков в плейлисте
  • получить массив альбомов в плейлисте, который уже был перетасован
  • используйте convertPlaylistToObjectByProperty для сортировки большого массива треков в объект с меньшими массивами, отсортированными по альбомам
  • рекомбинировать меньшие (теперь отсортированные) массивы треков обратно в большой массив треков, но теперь сгруппированных по альбомам
  • сгладить этот рекомбинированный массив, чтобы теперь он снова стал простым списком воспроизведения
  • передать этот плоский рекомбинированный массив в функцию createPlaylist

Я знаю, что мы еще не взялись за createPlaylist - оставим это напоследок.

Эта функция очень похожа на нашу последнюю функцию, но у byAlbumWithDiscography посередине другая логика. Как только у нас есть перемешанный массив альбомов из пользовательского плейлиста, мы выбрасываем фактический плейлист. Вместо этого мы перебираем массив albumIds и выполняем вызов API для получения треков для каждого из них, которые затем объединяем в один большой список воспроизведения.

  • Здесь есть один немного необычный шаблон кода:

В ES7 Javascript добавил ключевые слова async / await, но под капотом все еще использует обещания. Когда мы выполняем асинхронный вызов API в функции array.map, мы фактически возвращаем массив невыполненных обещаний, а не результат этих обещаний. Как ни странно, даже несмотря на то, что он полон невыполненных обещаний, сам массив создается синхронно, а это означает, что ожидание promArrayOfTracksFromAlbum не сработает. Вместо этого мы вызываем await Promise.all (обещаниеArrayOfTracksFromAlbum), которое создает новое обещание, которое разрешается после выполнения всех обещаний в массиве.

  • После разрешения Promise.all у нас есть массив массивов дорожек, поэтому мы сглаживаем его, как и раньше, и передаем результат в createPlaylist.

Это функция, которую мы используем для создания списка воспроизведения всей дискографии исполнителя, отображаемой в. Это почти то же самое, что и byAlbumWithDiscography, за исключением того, что вместо получения массива идентификаторов альбомов из списка воспроизведения мы получаем его, запрашивая SpotifyAPI альбомы, связанные с исполнителем. Пока мы занимаемся этим, давайте продолжим и подключим эту функцию с помощью кнопки Play Discography в:

Последняя функция spotifyFunction - createPlaylist

  • Вот и господа - последняя функция в spotofyFunctions.js и последний код проекта! Готовы создать плейлист и воспроизвести его?

Что ж, API Spotify не облегчает нам задачу. Несмотря на то, что у нас есть, казалось бы, удобные функции spotifyApi.createPlaylist и spotifyApi.play, они имеют некоторые условия:

  • Нам нужно получить UserId, прежде чем мы сможем создать список воспроизведения.
  • Мы должны сначала создать пустой список воспроизведения, а затем добавить в него треки.
  • Мы не можем добавлять более 100 треков за раз, поэтому, если у нас их больше 100, нам нужно вызывать spotifyApi.addTracksToPlaylist несколько раз.
  • Мы можем воспроизвести плейлист только в том случае, если у пользователя есть «активное устройство», но неясно, что на самом деле означает «активное устройство».
  • Независимо от того! Вот почему у нас есть специальная функция createPlaylist, которая справляется с этой сложностью. Логика функции в основном соответствует задачам, которые мы только что перечислили. chunk - отличная библиотека Lodash, которая разбивает большой массив на более мелкие. Также обратите внимание, что мы должны снова использовать конструкцию Promise.all для добавления треков, потому что это асинхронная операция внутри array.map.
  • Упс - уроки реальной жизни - отказ API
    Я знаю, вы были так взволнованы, и я тоже. Но у Spotify были другие планы. Короче говоря, между моментом, когда я начал этот проект, и моментом публикации блогов Spotify объявил об изменениях в своем API, а затем отказался от этих изменений, тем самым нарушив работу нашего приложения! Все, что они сделали, это изменили конечную точку для создания списка воспроизведения, но это означает, что наша библиотека spotofy-web-api-js не работает! Если бы я был лучшим гражданином, я бы сделал запрос на перенос библиотеки, чтобы исправить это, но быстрое решение - написать наш временный вызов API ajax для создания списков воспроизведения на данный момент вместо библиотеки. После обновления библиотеки мы вернем ее обратно.

Я не копировал весь файл в суть, потому что мы меняем только несколько вещей:

Теперь, когда нам нужен токен доступа за пределами библиотеки spotify-web-api-js, мы должны добавить глобальную переменную для его хранения, а также обновить setAccessToken.

Нам нужно вызвать нашу функцию tempCreatePlayist внутри нашей функции createPlaylist, которую мы написали выше.

Нам нужно создать нашу временную функцию, которая представляет собой просто ajax-вызов нужной нам конечной точки.

Работает!

  • Проверьте это - теперь вы должны иметь возможность войти в Spotify, выбрать один из своих плейлистов и переключаться по альбому. Вы также можете добавить соответствующую дискографию, а также создать дискографию по альбомам для Кейси Масгрейвс, Райана Бингхэма и Теда Лео (которые я настоятельно рекомендую слушать полностью) или добавить дань уважения вашим любимым артистам!
  • Кнопки не делают ничего визуального при нажатии, но если у вас есть телефон, открытый на странице списков воспроизведения рядом с вами, он должен начать воспроизведение через несколько секунд, в противном случае проверьте свои списки воспроизведения, чтобы увидеть метод перетасовки нового альбома и начать прослушивание олдскульный стиль!

  • Развертывание приложения create-response-app в рабочей среде
  • Последний шаг, если вы того пожелаете, - это развернуть ваше приложение, чтобы вы могли использовать его в безумном Интернете, а не только в своей локальной среде разработки. Это несложно, но этот процесс плохо документирован при использовании приложения create-react-app, как мы.
  • Одна из многих функций, которые create-response-app выполняет для нас под капотом при запуске и запуске сервера разработки с горячей перезагрузкой, но для производства сценарий сборки создает 1 файл Javascript, 1 файл CSS и один файл HTML.
  • Поскольку у нас есть только эти файлы, это означает, что нам нужно либо разместить их на существующем сервере, либо запустить простой сервер Express в Node, чтобы обслуживать эти файлы для нас. Мы собираемся пойти по этому пути, поэтому добавьте в корневой каталог новый файл с именем app.js. Это ОТЛИЧНЫЙ ФАЙЛ от App.js в папке компонентов, и мы напишем простой сервер для обслуживания этих файлов сборки:

Теперь, когда у нас есть сервер для размещения наших файлов сборки, нам нужен сценарий для его использования. Откройте свой package.json и давайте сделаем это.

  • В create-react-app уже есть хороший сценарий сборки для нас, поэтому для нашего сценария productionstart все, что нам нужно сделать, это запустить этот сценарий сборки, а затем запустить сервер. Обратите внимание, что мы также добавили выражение express как явную зависимость. В этом не должно быть необходимости, поскольку приложение create-react-app уже использует его на серверной части, но это приятно, чтобы навести порядок.
  • Последний файл, который нам нужно добавить, - это Procfile (с заглавной буквы, без точки), который содержит инструкции для службы развертывания (первоначально Heroku, но мы будем использовать службу Cosmic JS). Procfile сообщит службе, что нужно развернуть один веб-узел и запустить наш сценарий productionstart.

Так близко, что мы можем попробовать! Cosmic JS упрощает развертывание прямо из репозитория Github (вы ведь загружали свои коммиты git, верно?). Все, что вам нужно сделать, это вернуться к панели инструментов Cosmic JS, и под настройками есть опция веб-развертывания. Оттуда вы просто нажимаете синюю кнопку Deploy to Cosmic JS. Вам потребуется несколько минут, чтобы настроить и отправить вам электронное письмо, когда ваша производственная версия Old School Shuffle будет запущена.

  • Самым, самым, самым последним, что сейчас является то, что нам нужно установить переменные окружения в нашем развертывании Cosmic JS, чтобы отразить наш файл .env из разработки. Совет: не забудьте нажать кнопку «Установить переменные среды» и дать ей несколько минут на обновление.

Последние штрихи

  • Теперь, когда наше приложение действительно работает, оно мне немного больше нравится, поэтому я классифицировал CSS, чтобы придать ему немного привлекательности. Эти незначительные изменения не отображаются в github gists, но они отражены в репозитории.

Вот и все!

А теперь наслаждайтесь плодами своего труда! Спасибо, что присоединились ко мне, и я надеюсь, вам понравилось, и вы кое-что узнали. Это мое первое руководство по программированию, поэтому, пожалуйста, оставьте комментарий, если я что-то пропустил… или если у вас есть какие-либо комментарии!

Свяжитесь с нами в Twitter и присоединитесь к нашему сообществу Slack.