Код
#статьи

React.js для новичков в программировании: что это, как устроен и зачем нужен

Если стажёр или совсем зелёный джун попросят вас объяснить, что такое React.js, — просто покажите им эту статью.

Иллюстрация: OlyaSnow для Skillbox Media

В интернете полно руководств по React.js с названиями типа for dummies, for idiots — вроде бы для чайников. Но они по большей части негуманны и довольно сложны — человеку без знания JavaScript пользы не будет, только сильнее запутается и почувствует себя тем самым dummy. Поэтому мы решили максимально просто объяснить, что такое React.js и для чего он нужен, и даже показать, как на нём написать небольшую онлайн-игру.

Вы узнаете:


Что такое React.js

React.js — это JavaScript-библиотека от «Фейсбука»* для удобной разработки интерфейсов, то есть внешней части сайтов и приложений, с которой взаимодействует пользователь.

Главная фишка React.js — компоненты и состояния.

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

Состояние — это вся информация об элементе, в том числе о его отображении. Например, состояние объекта «термометр» может описываться свойствами current_temperature, min и max.

Что такое компоненты и состояния: переводим на понятный язык

Пока звучит немного абстрактно и сложно, но на деле всё гораздо проще. Потренируемся на Цукерберге: в конце концов, это его детище — ему и отвечать.

На скриншоте три крупных компонента — пост в ленте «Фейсбука»*, блок краткой информации и блок с выводом фотографий. В каждый из них входят более мелкие компоненты. Например, внутри поста есть текст, изображение, аватарка, имя автора, лайки, комментарии, различные информационные элементы. Внутри блока с фотографиями — отдельные фото, а внутри блока с краткой информацией — собственно та самая краткая информация.

Скриншот: Skillbox Media

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

Посмотрите, как в зависимости от состояния меняется размер аватарки:

Скриншот: Skillbox Media
  • Большая — в шапке личной страницы.
  • Стандартная — в верхнем меню и записи в ленте.
  • Совсем крошечная — в строке «у вас столько-то подписчиков».

Уже получилось три состояния, но это не предел — ведь внешний вид аватарки различается в мобильной и десктопной версиях, в приложениях для Android, iOS и так далее. Отметим, что аватарка практически везде будет вложенной — в составе более крупных компонентов React.js, таких как пост, шапка, боковая панель или меню.

В React.js есть собственные средства для управления состояниями, но на практике в средних и крупных проектах чаще используют Redux — сторонний менеджер состояний. Он удобнее и лучше масштабируется.

Зачем нужен React.js, если есть HTML, JavaScript и CSS

Никаких огородов. React.js — это всего лишь способ в удобном виде представить код JavaScript и HTML, сделать его повторяемым и наглядным. Компоненты React.js пишут на особом языке — JSX, который выглядит как смесь JavaScript и HTML. Вот пример кода на этом языке:

const name = 'Josh Perez';
const element = <h1>Привет, {name}</h1>;
ReactDOM.render(
  element,
  document.getElementById('root')
);
JSX-код — то, что кажется HTML-тегом <h1>, на самом деле элемент JSX

Код JSX довольно наглядный, и, кстати, то, что похоже на HTML, — вовсе не HTML :) Звучит галлюциногенно, но это просто синтаксис JSX.

Браузеру понимать JSX не нужно — код React.js транслируется в JavaScript, с которым знаком любой уважающий себя браузер. Для этого написанное на React.js приложение прогоняют, например, через Babel — специальную программу-транспайлер, которая переводит разные представления (то есть языки вроде JSX) в JavaScript-код.

function getGreeting(user) {
  if (user) {
   return <h1>Здравствуй, {formatName(user)}!</h1>;
 }
 return <h1>Здравствуй, незнакомец.</h1>;
}

JSX-код

function getGreeting(user) {
  if (user) {
    return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, ", formatName(user), "!");
  }
  return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, незнакомец.");
}
JavaScript-код после Babel

На первый взгляд, механика странная. Кажется, это как если бы Достоевский придумал свой собственный язык, писал на нём книги, а потом их переводили бы на русский и только после этого издавали. И это была бы хорошая аналогия — но только если бы книги Достоевского переводились на русский автоматически, а писать на новом языке было бы в несколько раз быстрее.

У React.js есть три мощных преимущества:

  • JSX гораздо проще читать и понимать, чем JavaScript, а значит, на поддержку и отладку кода тратится гораздо меньше времени разработчиков (а это зарплаты и скорость новых релизов).
  • В нём удобно реализована система компонентов — повторяющихся частей кода, которые используются в разных условиях и обстоятельствах и меняются в зависимости от контекста.
  • Каждый компонент зависит только от своего состояния — а значит, гораздо легче устранять ошибки в коде, если что-то не работает или работает не так, как ожидалось. То есть ошибки становятся очевидными: компонент, который работает корректно сам по себе, всегда будет работать корректно — если только ему не передать какое-то неправильное состояние.

В итоге React.js помогает сэкономить время, делает код более понятным и структурированным, даёт возможность переиспользовать большие блоки. Всё это помогает значительно снизить стоимость разработки, поддержки, обновления и отладки приложений, а также делать их значительно быстрее. К тому же, зная JavaScript и HTML, выучить его довольно просто — для основ хватит нескольких дней. React.js эффективен только на проектах с большим числом динамических страниц. Делать на React.js сайт-визитку — это перебор.

Конкуренты React.js

У React.js есть и свои конкуренты. Например, библиотеки Vue.js и Angular. На них тоже пишут пользовательские интерфейсы, у каждого есть свои плюсы и минусы. Пока что работодатели чаще ждут от разработчиков знания React.js — в марте 2023 года на hh.ru он встречался в требованиях 3300 раз, Vue.js — 1782 раза, а Angular — 1282 раза.

Согласно исследованию Stack Overflow, React.js был вторым по популярности веб-фреймворком в 2022 году, уступая лишь Node.js. Он даже обогнал динозавра jQuery, который разработчики уже несколько лет ненавидят (по данным того же исследования), но массово продолжают использовать. Раньше эта библиотека применялась во многих сайтах и веб-приложениях — не переписывать же их код :) Четвёртое место занял фреймворк для Node.js — Express. А конкуренты React.js — Angular и Vue.js — пятое и шестое место соответственно.

Скриншот: Stack Overflow

А ещё существует React Native — тоже разработка «Фейсбука»*, которую не следует путать с обычным React.js. В какой-то момент компания поняла, что на React.js пишут приложения не только для браузеров, но и для разных операционных систем. Правда, работали такие приложения довольно медленно. Чтобы решить эту проблему, в «Фейсбуке»* и создали нативную версию библиотеки.

Синтаксис React Native похож на JSX, но переводится на понятный и привычный для Windows, macOS, Android и других операционных систем язык. То есть приложение становится нативным — использует стандартные для разных платформ возможности и протоколы, а не запускается в браузере. Мало того, на платформе React Native можно использовать и другие языки программирования — например, Java, Swift, Objective-C.

Где скачать React.js и как начать им пользоваться

Получить доступ к React.js можно двумя способами.

Использовать онлайн-редакторы кода

Это самый простой способ. Можно поиграться с библиотекой в онлайн-песочницах CodePen и CodeSandBox или скачать HTML-файл с шаблоном c GitHub. После этого свой код можно прогнать через Babel — тоже онлайн, чтобы не устанавливать лишние приложения.

Установить React.js на компьютер

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

Для этого предварительно нужно установить Node.js — это среда, которая позволяет запускать JS-код как серверное приложение.

Затем скачайте пакет create-react-app с помощью npm:

npm i -g create-react-app

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

create-react-app my-first-app

Если всё будет ОК, Node.js в конце сообщения выведет Happy hacking!.

Запустите приложение:

cd my-first-app
npm start

С помощью команды cd мы перешли в папку проекта, а командой start запустили локальный сервер разработки http://localhost:3000/. В результате вы должны увидеть в браузере такую красоту:

Изображение: Skillbox Media

Разработка и настройка простого React-приложения

Напишем на React.js веб-версию бессмертного хита — игры «крестики-нолики». Весь код, за исключением стилей, будем писать в файле App.js в папке src.

Сначала импортируем модуль React, вебхук из неё и библиотеку ReactDOM для рендеринга компонентов:

import React, { useState } from "react";
import ReactDOM from "react-dom";

Логику игры будем писать в компоненте App, который уже содержит код. Можете его полностью удалить — он нам не пригодится:

function App() {
   /*Здесь будет логика приложения*/
  };

С помощью useState создадим хук, который возвращает массив squares, — он будет хранить клетки игрового поля:

function App() {
  const [squares, setSquares] = useState(Array(9).fill(null));

  };

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

Создадим второй хук для хранения очереди (кто ходит следующим: X или 0):

function App() {
  const [squares, setSquares] = useState(Array(9).fill(null));
  const [xIsNext, setXIsNext] = useState(true);
 
  };

По умолчанию состояние устанавливается в true — это значит, что первыми будут ходить крестики. Функция setXIsNext переключает очереди игроков.

На каждом ходе надо проверять, не определился ли победитель. Для этого напишем функцию calculateWinner:

const calculateWinner = (squares) => {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
};

В calculateWinner передаётся массив с текущими значениями клеток игрового поля. Во внутреннем массиве lines содержатся выигрышные комбинации полей. Функция перебирает их, подставляя на место индексов входного массива, и, если все три значения совпадут, возвращает победителя (X или 0) или null, если победителя нет.

Значение calculateWinner хранится в переменной winner:

function App() {
  const [squares, setSquares] = useState(Array(9).fill(null));
  const [xIsNext, setXIsNext] = useState(true);
  const winner = calculateWinner(squares);
  };

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

function App() {
 {
    /* Остальной код */

    const handleClick = (i) => {
        const squaresCopy = [...squares];
        if (winner || squaresCopy[i]) return;
        squaresCopy[i] = xIsNext ? "X" : "O";
        setSquares(squaresCopy);
        setXIsNext(!xIsNext);
  };

Следующая функция будет рисовать клетки поля, которые на самом деле являются обыкновенными HTML-кнопками. renderSquare принимает номер квадрата и возвращает кнопку, на которую можно кликнуть и сделать ход:

const renderSquare = (i) => {
    return (
      <button className="square" onClick={() => handleClick(i)}>
        {squares[i]}
      </button>
    );
  };

Пусть программа выводит статус игры над полем. Если есть победитель, то статус будет «Победитель: X» или «Победитель: 0». Если же победителя нет — «Следующий игрок: X» или «Следующий игрок: 0».

const status = winner
    ? `Winner: ${winner}`
    : `Next player: ${xIsNext ? "X" : "O"}`;

Теперь пропишем JSX-элементы, которые будет возвращать функция App, — они и будут отображаться на странице:

<div className="game-field">
      <div className="status">{status}</div>
      <div className="board-row">
        {renderSquare(0)}
        {renderSquare(1)}
        {renderSquare(2)}
      </div>
      <div className="board-row">
        {renderSquare(3)}
        {renderSquare(4)}
        {renderSquare(5)}
      </div>
      <div className="board-row">
        {renderSquare(6)}
        {renderSquare(7)}
        {renderSquare(8)}
      </div>
    </div>

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

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

html, body {
    height: 100%;
    font-size: 30px;
}


#root {
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;    
}


.flex {
    display: flex;
  }
 


  button {
    width: 100px;
    height: 100px;
    font-size: 30px;
    color: red;
  }

Подключите файл директивой import:

import "./styles.css";

И добавьте в каждый ряд (элементы div с атрибутом className="board-row") класс flex.

Обратите внимание: слово class в JavaScript зарезервировано для других целей, поэтому имя класса элемента в нём указывают с помощью аналога — className.

Весь код проекта:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";


function App() {
 const [squares, setSquares] = useState(Array(9).fill(null));
 const [xIsNext, setXIsNext] = useState(true);
 const winner = calculateWinner(squares);

 const handleClick = (i) => {
   const squaresCopy = [...squares];
   if (winner || squaresCopy[i]) return;
   squaresCopy[i] = xIsNext ? "X" : "O";
   setSquares(squaresCopy);
   setXIsNext(!xIsNext);
 };

 const renderSquare = (i) => {
   return (
     <button className="square" onClick={() => handleClick(i)}>
       {squares[i]}
     </button>
   );
 };

 const status = winner
   ? `Winner: ${winner}`
   : `Next player: ${xIsNext ? "X" : "O"}`;

 return (
   <div className="game-field">
     <div className="status">{status}</div>
     <div className="board-row flex">
       {renderSquare(0)}
       {renderSquare(1)}
       {renderSquare(2)}
     </div>
     <div className="board-row flex">
       {renderSquare(3)}
       {renderSquare(4)}
       {renderSquare(5)}
     </div>
     <div className="board-row flex">
       {renderSquare(6)}
       {renderSquare(7)}
       {renderSquare(8)}
     </div>
   </div>
 );
};

const calculateWinner = (squares) => {
 const lines = [
   [0, 1, 2],
   [3, 4, 5],
   [6, 7, 8],
   [0, 3, 6],
   [1, 4, 7],
   [2, 5, 8],
   [0, 4, 8],
   [2, 4, 6]
 ];
 for (let i = 0; i < lines.length; i++) {
   const [a, b, c] = lines[i];
   if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
     return squares[a];
   }
 }
 return null;
};

А вот как должна выглядеть игра в окне браузера:

Изображение: Skillbox Media

Итог

React.js — довольно простая библиотека, хотя, как и в любом деле, здесь есть нюансы. Например, вебхуки, однонаправленная передача данных, callback-функции, виртуальный DOM, методы жизненного цикла. Написать новый «Фейсбук»* или «Инстаграм»* на React.js не так-то просто, но всё равно это очень дружественная библиотека.

Обязательно ознакомьтесь с документацией проекта и учебником по синтаксису JSX на официальном сайте React.js. Начните с Hello, World! и смело экспериментируйте в CodePen — так советуют авторы гайда.

Как обычно, легче всего осваивать технологию на реальных задачах — например, поставьте себе цель скопировать часть интерфейса «Фейсбука»* или «Инстаграма»*. Почему бы и нет?

Больше интересного про код в нашем телеграм-канале. Подписывайтесь!


* Решением суда запрещена «деятельность компании Meta Platforms Inc. по реализации продуктов — социальных сетей Facebook и Instagram на территории Российской Федерации по основаниям осуществления экстремистской деятельности».

Проверьте свой английский. Бесплатно ➞
Нескучные задания: small talk, поиск выдуманных слов — и не только. Подробный фидбэк от преподавателя + персональный план по повышению уровня.
Пройти тест
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована