Современное обновление React-разработки в 2022 году

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

Уже рассмотрев разработку Vue в нашей предыдущей статье из цикла сравнения веб-фреймворков, было бы справедливо дать React равный шанс, продемонстрировав его возможности и сокровища, созданные сообществом.

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

Мы создадим сайт для публичного обмена короткими сообщениями под названием «ithink». Это как Twitter, только без аккаунтов и без возможности удалить то, что вы публикуете.

ithink-corp / react

Официальная реализация ithink, сделанная на React и работающая на Cyclic.

ithink, powered by Cyclic

Запустите его на своей машине:

npm install
npm dev
Войти в полноэкранный режим Выйти из полноэкранного режима

Посмотреть на GitHub

Во-первых, нам нужен API

Если вы поиграете с CodePen выше, то быстро поймете, что база данных — это не фальшивка.

На самом деле у нас есть внутренняя сторона нашего приложения: она обрабатывает хранение и получение простых текстовых данных. Она также построена на службе хранения объектов S3 от Amazon.

ithink-corp / api

Официальный API для ithink, работающий на базе Cyclic.

Официальный API ithink, построенный на Cyclic.sh

Это пример REST API, разработанный для развертывания на Cyclic.sh.

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

Узнайте, как использовать API ithink, используя команду curl.

Вывести список всех элементов

curl "https://ithink-api.cyclic.app/" -H "Content-Type: application/json"
Вход в полноэкранный режим Выйти из полноэкранного режима

Создать новый элемент

curl "https://ithink-api.cyclic.app/" --data '{"text": "Say something nice!"}' -H "Content-Type: application/json"
Войти в полноэкранный режим Выйти из полноэкранного режима

Просмотр на GitHub

Обычно разработчик тратит часы и часы на настройку такой базы данных, и это тоже не бесплатно. К счастью для нас, при использовании Cyclic мы получаем бесплатный экземпляр хранилища AWS S3. Никакой кредитной карты не требуется.

Как создать новый проект React?

Новичку не нужно ничего создавать с нуля.

Это факт, и сообщество React признает его настолько, что создало полностью интерактивную программу, которая помогает новичкам создавать свои проекты без особых хлопот.

Она называется create-react-app и использует Babel и webpack под капотом, но вам не нужно ничего о них знать. Но я буду безответственным, если скажу, что вы никогда не столкнетесь с этими двумя программами, поэтому я рекомендую сохранить эти статьи о webpack и Babel. Прочитайте их, когда будете готовы.

Наконец-то пришло время использовать это волшебное программное обеспечение. Убедитесь, что на вашей машине установлены NodeJS и NPM, затем запустите терминал и выполните следующую команду в выбранной вами директории:

npx create-react-app my-app
cd my-app
npm start
Войти в полноэкранный режим Выйти из полноэкранного режима

Если вы не используете Linux или MacOS для программирования, ознакомьтесь с этой шпаргалкой, в которой описаны аналоги наших команд в Windows.

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

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

Независимо от того, какой стартер нам выдается, когда мы запускаем create-react-app, первый шаг заключается в том, чтобы фактически стереть все это. Да, вы правильно меня услышали; мы собираемся стереть почти все, что делает эта волшебная программа.

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

rm src/* -r # erase all files in the src/ folder
touch src/index.js # create a new file called "index.js" in the src/ folder
Войти в полноэкранный режим Выйти из полноэкранного режима

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

mkdir src/components src/utils # create two directories in the src/ folder
Вход в полноэкранный режим Выход из полноэкранного режима

Как следует из названия, компоненты (например, всплывающий модал) будут находиться в папке components/, а полезные функции (например, функция для отправки данных на сервер) — в папке utils/.

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

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

Как развернуть проект React в Интернете?

Создать целое приложение на своем локальном компьютере достаточно сложно, это целая индустрия с названием «Frontend Development». Фронтенд-разработчик не должен беспокоиться о тонкостях, связанных с серверами и развертыванием.

К счастью для нас, Cyclic дает нам возможность бесплатно развернуть React-приложения в облаке, просто нажав одну кнопку и добавив один скрипт в наше приложение. С помощью Cyclic’s React starter мы знаем, что нужно добавить следующий скрипт в корень нашего проекта:

// /server.js

const express = require('express')
const path = require("path");
const app = express()

// This configures static hosting for files in /public that have the extensions
// listed in the array.
var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html','css','js','ico','jpg','jpeg','png','svg'],
  index: ['index.html'],
  maxAge: '1m',
  redirect: false
}
app.use(express.static('build', options))

const port = process.env.PORT || 3000

app.listen(port, () => {
  console.log(`React app listening at http://localhost:${port}`)
})
Войти в полноэкранный режим Выйти из полноэкранного режима

Также важно добавить следующие изменения в файл package.json:

{
    "scripts": {
        - "start": "react-scripts start",
        + "start": "node server.js",
    + "dev": "react-scripts start",
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

После этого все, что требуется для запуска нашего приложения во всемирную паутину — это создать учетную запись Cyclic и нажать кнопку DEPLOY. Поверьте, это так приятно, когда приложение делает всю работу за вас! И вы даже можете выбрать свой собственный бесплатный поддомен после этого! 😃

Как мы создаем компонент в React?

На данный момент наше приложение не функционирует. Это связано с тем, что скрипт index.js все еще пуст, и это потому, что мы только что его создали.

Давайте узнаем новый факт о React: каждое приложение должно иметь один главный компонент. Это как элемент <body>, где хранится все содержимое. React размещает внутренности главного компонента внутри элемента верхнего уровня #root, как показано на следующем изображении:

Как вы уже догадались, мы создаем этот главный компонент внутри файла index.js. Это может показаться пугающим — создавать что-то с нуля… Но это не так, потому что это всегда похоже на следующий шаблон:

// The imports
import React from 'react'
import ReactDOM from 'react-dom/client'

// The component
class App extends React.Component {
        // The JavaScript Logic
        constructor(props) {
            super(props)
        }

        // The HTML Markup
        // Notice how we use className instead of class; this is important!
        // read this: https://reactjs.org/docs/dom-elements.html
    render() {
                return (
                    <div>
                        <header className="...">
                            <h1>ithink</h1>
                            <button>
                                New
                            </button>
                        </header>
                    </div>
                )
        }
}

// Injecting the component inside the #root element
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<App />)
Вход в полноэкранный режим Выход из полноэкранного режима

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

Но есть еще одна вещь, которая все еще выделяется, и она, несомненно, является новой для всех начинающих разработчиков React. Это «странная» смесь кода JavaScript и разметки HTML. Этот странный формат называется JSX — Java*Script Ex*tension. Все, что вам пока нужно знать о нем, это то, что он делает включение HTML-разметки в код JavaScript нормальным.

  • Но это не всегда работает!

    С JSX это не нормально:

    render() {
        <article>...</article>
        <article>...</article>
    }
    

    Но это:

    render() {
        <div>
            <article>...</article>
            <article>...</article>
        </div>
    }
    

    Урок усвоен: всегда оборачивайте HTML-разметку вокруг одного и только одного элемента.

Как слушать события нажатия в React?

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

class App extends React.Component {
    ...
    render() {
        return (
            <div>
                ...
                <button onClick="this.toggleModal">New</button>
            </div>
        )
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

class App extends React.Component {
    ...
    // Bad! :(
    toggleModal() {
        // do stuff...
    }

    // Okay :)
    toggleModal = () => {
        // do stuff...
    }
    ...
}
Вход в полноэкранный режим Выйти из полноэкранного режима

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

Как создать переключатель в React?

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

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

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isModalOpen: false,
        }
    }
        ...
}
Войти в полноэкранный режим Выход из полноэкранного режима

Переключатели были бы не очень интересными, если бы мы не могли их переключать. Эта логика относится к методу компонента, который мы создали ранее. К сожалению, мутирование переменных с состоянием довольно неинтуитивно:

toggleModal = () => {
    // Wrong! :(
    this.state.isModalOpen = true

    // Correct! :)
    this.setState({
        isModalOpen: true
    })
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Как создать несколько компонентов в React?

Помимо основного компонента, приложения состоят из множества частей пользовательского интерфейса, которые должны быть организованы эффективным образом. Мы создали папку components/ именно для этого; пришло время наконец-то использовать ее!

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

// components/modal.js

export function NewModal(props) {
  // notice the use of 'htmlFor' instead of 'for'
  // read this to understand why: https://reactjs.org/docs/dom-elements.html
  return (
    <div>
      <dialog open>
        <main>
          <form method="dialog">
            <label htmlFor="content">Content</label>
            <textarea id="content" autoFocus></textarea>

            <div>
              <button value="cancel">Cancel</button>
              <button value="default">Post</button>
            </div>
          </form>
        </main>
        <footer>
          <p>Whatever you write will become public.</p>
        </footer>
      </dialog>
    </div>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

import { Modal } from './components/modal'

class App extends React.Component {
    ...
    render() {
        return (
            <div>
                ...
                <Modal />
            </div>
        )
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Мы также не можем забыть о логике переключения, которую мы только что реализовали в последнем разделе этой статьи, поэтому мы должны использовать ее. Легко сказать React, чтобы он условно показывал элемент на основе булевой переменной состояния. Синтаксис, который я собираюсь представить, довольно новый, и он является особенным для JSX:

{ this.state.isModalOpen && <Modal/> }
Войти в полноэкранный режим Выйти из полноэкранного режима

Двойные скобки являются ключом к объединению логики JavaScript с разметкой HTML. Они могут содержать практически все — от вычислений до манипуляций со строками и даже списки HTML-элементов, как мы скоро увидим в этом руководстве:

{ 'Hello' }
{ 5 + 5 }
{ 'Hello' + ' World' }
Вход в полноэкранный режим Выход из полноэкранного режима

Эта изящная особенность JSX называется интерполяцией, и мы можем даже объединить ее с логическим оператором AND (&&) JavaScript для условного отображения HTML-разметки в зависимости от различных возможностей:

{ false && <div></div> /* will NEVER display */ }
{ true && <div></div> /* will ALWAYS display */ }
{ condition && <div></div> /* will ONLY display if condition is TRUE */ }
Войти в полноэкранный режим Выход из полноэкранного режима

Как отправить данные на сервер с помощью компонента React?

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

export function NewModal(props) {
  async function onSubmit(e) {
    e.preventDefault()
    // TODO: submit data to the server
  }

  return (
    <div>
      <form onSubmit={onSubmit}>
        ...
      </form>
    </div>
  )
}
Вход в полноэкранный режим Выход из полноэкранного режима

Но хотя все это для нас забавы и игры, все же важно задать следующий вопрос: как нам получить значение input в React? Чтобы ответить на этот, казалось бы, простой вопрос, я должен познакомить вас с React Hooks, самыми важными концепциями в современной разработке. И хотя они немного выходят за рамки этого руководства, мы будем использовать удобный хук для создания переменных состояния для компонентов, основанных на функциях.

import { useState } from 'react'

export function NewModal(props) {
  const [message, setMessage] = useState('')
  ...

  return (
    ...
    <textarea
      value={message}
      onChange={(event) => setMessage(event.target.value)}
    />
  )
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Это удивительно просто! С помощью хука useState мы можем как получить доступ к переменной состояния message, так и изменить ее с помощью ее собрата setMessage. С помощью этих двух элементов мы использовали интерполяцию JSX для установки значения текстовой области и реагировали на события изменения путем обновления состояния. Ожидайте увидеть этот паттерн снова и снова в приложениях React.

import { postMessage } from '../utils/server'

// it's now easy to post data to the server!
async function onSubmit(e) {
    e.preventDefault()
    await postMessage(message)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы все еще не можем отправить данные на сервер, не написав для этого скрипт. В качестве вспомогательной функции мы поместим эту логику в новый файл server.js в каталоге utils/. Здесь нет ничего нового, просто обычная функция fetch() для связи с нашим сервером.

// utils/server.js

export async function postMessage(message) {
    await fetch('https://ithink-api.cyclic.app/', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            text: message,
        }),
    })
}
Вход в полноэкранный режим Выход из полноэкранного режима

Как в React закрыть модальное окно при нажатии на него снаружи?

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

К счастью, нам не придется делать много кода самостоятельно благодаря замечательному сообществу React. Будучи такой важной функцией, опытные разработчики уже реализовали ее и отправили вместе с десятками других небольших утилит в виде хуков. (Да, хуки снова заявляют о себе; я говорил вам, что это очень важные концепции!) Все это упаковано в удобную библиотеку под названием react-use.

import { useRef } from 'react'
import { useClickAway } from 'react-use'

export function NewModal(props) {
        ...

    const containerRef = useRef(null)
    useClickAway(containerRef, () => props.onClose())

        return (
            <div>
                <dialog ref={ containerRef }>...</dialog>
            </div>
        )
}
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, как мы используем еще один хук, useRef. Это один из самых популярных хуков, потому что его функция очень важна. Хук useRef дает нам доступ к DOM; использовать его так же просто, как добавить атрибут ref к нужному HTML-элементу, как показано в приведенном выше фрагменте кода.

Как отобразить список элементов в React?

Хорошие новости! Мы закончили с модальным компонентом! Но нам все еще не хватает одной важной части нашего приложения: списка сообщений. Здесь не так много нового, поэтому давайте просто создадим новый файл компонента с именем message-list.js в каталоге components/, как обычно.

// index.js
import { MessageList } from './components/message-list'

render() {
    return (
        <div>
            ...
            <main><MessageList /></main>
        </div>
    )
}

// components/message-list.js

export function MessageList(props) {
    if (props.messages) {
        // Display list of messages
        return (
            <div></div>
        )
    } else {
        // Display loading skeleton
        return (
            <div></div>
        )
    }
}
Вход в полноэкранный режим Выйдите из полноэкранного режима

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

Помните JSX-интерполяцию? Есть кое-что очень интересное, что мы можем сделать с помощью этой волшебной функции. Можно использовать метод Array map() для возврата динамического списка HTML-элементов!

<div>
    { props.messages.map(({ message }) => <p key={message}>{ message }</p>) }
</div>
Вход в полноэкранный режим Выход из полноэкранного режима

Разве это не удивительно? Мы можем сделать то же самое для отображения загрузочного скелета.

<div>
    { Array.from(Array(20).keys()).map((number) => <div key={number}></div>) }
</div>
Вход в полноэкранный режим Выход из полноэкранного режима

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

Как загрузить список данных с сервера с помощью компонента React?

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

class App extends React.Component {
    constructor(props) {
            super(props)
            this.state = {
                ...,
                messages: null
            }
        }
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

class App extends React.Component {
    ...
    componentDidMount() {
        // load items
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

С помощью хука жизненного цикла compnentDidMount мы можем запустить все, что захотим, когда компонент будет окончательно отрисован, а это именно то, что мы искали. После этого нам остается заполнить переменную состояния messages данными с сервера.

import { getMessages } from './utils/server'

class App extends React.Component {
    ...
    componentDidMount() {
        const messages = await getMessages()

                this.setState({
                    messages: messages,
                })
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

// utils/server.js

export async function getMessages() {
    const res = await fetch('https://ithink-api.cyclic.app/', {
        headers: {
            'Content-Type': 'application/json',
        },
    })
    const items = await res.json()
    return items.map((item) => ({
        message: item,
    }))
}
Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

И вуаля, наше приложение готово, вот так! Процесс разработки React, безусловно, уникален, и вы можете сразу заметить много отличий от процесса разработки VueJS, который мы рассматривали в нашей прошлой статье.

Мы рассмотрели многие особенности React:

  • Создание новых проектов с помощью create-react-app,
  • прослушивание и обработка событий,
  • хуки и библиотека react-use,
  • пользовательские компоненты,
  • интерполяция JSX,
  • переменные с состоянием,
  • динамические списки.
  • Ссылки на DOM.

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

Оцените статью
devanswers.ru
Добавить комментарий