HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#статьи</a></p>
1 <p><a>#статьи</a></p>
2 <ul><li>3 апр 2023</li>
2 <ul><li>3 апр 2023</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><p>Если стажёр или совсем зелёный джун попросят вас объяснить, что такое React.js, - просто покажите им эту статью.</p>
4 </ul><p>Если стажёр или совсем зелёный джун попросят вас объяснить, что такое React.js, - просто покажите им эту статью.</p>
5 <p>Иллюстрация: OlyaSnow для Skillbox Media</p>
5 <p>Иллюстрация: OlyaSnow для Skillbox Media</p>
6 <p>Фанат Free Software Foundation, использует Linux и недолюбливает Windows. Пишет истории про кодинг и программы на Python. Влюблён в Lisp, но пока что не умеет на нём программировать.</p>
6 <p>Фанат Free Software Foundation, использует Linux и недолюбливает Windows. Пишет истории про кодинг и программы на Python. Влюблён в Lisp, но пока что не умеет на нём программировать.</p>
7 <p>В интернете полно руководств по React.js с названиями типа for dummies, for idiots - вроде бы для чайников. Но они по большей части негуманны и довольно сложны - человеку без знания JavaScript пользы не будет, только сильнее запутается и почувствует себя тем самым dummy. Поэтому мы решили максимально просто объяснить, что такое React.js и для чего он нужен, и даже показать, как на нём написать небольшую онлайн-игру.</p>
7 <p>В интернете полно руководств по React.js с названиями типа for dummies, for idiots - вроде бы для чайников. Но они по большей части негуманны и довольно сложны - человеку без знания JavaScript пользы не будет, только сильнее запутается и почувствует себя тем самым dummy. Поэтому мы решили максимально просто объяснить, что такое React.js и для чего он нужен, и даже показать, как на нём написать небольшую онлайн-игру.</p>
8 <p>Вы узнаете:</p>
8 <p>Вы узнаете:</p>
9 <ul><li><a>Что такое React.js</a></li>
9 <ul><li><a>Что такое React.js</a></li>
10 <li><a>Что такое компоненты и состояния</a></li>
10 <li><a>Что такое компоненты и состояния</a></li>
11 <li><a>Зачем нужен React.js</a></li>
11 <li><a>Зачем нужен React.js</a></li>
12 <li><a>Какие у него аналоги</a></li>
12 <li><a>Какие у него аналоги</a></li>
13 <li><a>Где его скачать и как начать пользоваться</a></li>
13 <li><a>Где его скачать и как начать пользоваться</a></li>
14 <li><a>Как написать и настроить простой проект на React.js</a></li>
14 <li><a>Как написать и настроить простой проект на React.js</a></li>
15 </ul><p>React.js - это JavaScript-библиотека от "Фейсбука"* для удобной разработки интерфейсов, то есть внешней части сайтов и приложений, с которой взаимодействует пользователь.</p>
15 </ul><p>React.js - это JavaScript-библиотека от "Фейсбука"* для удобной разработки интерфейсов, то есть внешней части сайтов и приложений, с которой взаимодействует пользователь.</p>
16 <p>Главная фишка React.js - компоненты и состояния.</p>
16 <p>Главная фишка React.js - компоненты и состояния.</p>
17 <p>Компонент - это кусочек кода, который отвечает за внешний вид одного из элементов сайта или приложения. Причём такие кусочки-компоненты могут быть вложенными.</p>
17 <p>Компонент - это кусочек кода, который отвечает за внешний вид одного из элементов сайта или приложения. Причём такие кусочки-компоненты могут быть вложенными.</p>
18 <p>Состояние - это вся информация об элементе, в том числе о его отображении. Например, состояние объекта "термометр" может описываться свойствами current_temperature, min и max.</p>
18 <p>Состояние - это вся информация об элементе, в том числе о его отображении. Например, состояние объекта "термометр" может описываться свойствами current_temperature, min и max.</p>
19 <p>Пока звучит немного абстрактно и сложно, но на деле всё гораздо проще. Потренируемся на Цукерберге: в конце концов, это его детище - ему и отвечать.</p>
19 <p>Пока звучит немного абстрактно и сложно, но на деле всё гораздо проще. Потренируемся на Цукерберге: в конце концов, это его детище - ему и отвечать.</p>
20 <p>На скриншоте три крупных компонента - пост в ленте "Фейсбука"*, блок краткой информации и блок с выводом фотографий. В каждый из них входят более мелкие компоненты. Например, внутри поста есть текст, изображение, аватарка, имя автора, лайки, комментарии, различные информационные элементы. Внутри блока с фотографиями - отдельные фото, а внутри блока с краткой информацией - собственно та самая краткая информация.</p>
20 <p>На скриншоте три крупных компонента - пост в ленте "Фейсбука"*, блок краткой информации и блок с выводом фотографий. В каждый из них входят более мелкие компоненты. Например, внутри поста есть текст, изображение, аватарка, имя автора, лайки, комментарии, различные информационные элементы. Внутри блока с фотографиями - отдельные фото, а внутри блока с краткой информацией - собственно та самая краткая информация.</p>
21 <em>Скриншот: Skillbox Media</em><p>У каждого из этих компонентов есть состояния. Например, блок краткой информации будет по-разному выглядеть в мобильной и десктопной версиях, у сердечка меняется число с лайками или цвет (если вы лайкнули или не лайкнули запись), а пост может обрезать текст, показывать содержимое полностью, меняться в зависимости от содержания. Ведь содержание поста - это тоже его состояние. Именно в этом проявляется гибкость и сила React.js: вы пишете компонент один раз, а потом просто передаёте ему разные состояния.</p>
21 <em>Скриншот: Skillbox Media</em><p>У каждого из этих компонентов есть состояния. Например, блок краткой информации будет по-разному выглядеть в мобильной и десктопной версиях, у сердечка меняется число с лайками или цвет (если вы лайкнули или не лайкнули запись), а пост может обрезать текст, показывать содержимое полностью, меняться в зависимости от содержания. Ведь содержание поста - это тоже его состояние. Именно в этом проявляется гибкость и сила React.js: вы пишете компонент один раз, а потом просто передаёте ему разные состояния.</p>
22 <p>Посмотрите, как в зависимости от состояния меняется размер аватарки:</p>
22 <p>Посмотрите, как в зависимости от состояния меняется размер аватарки:</p>
23 <em>Скриншот: Skillbox Media</em><ul><li>Большая - в шапке личной страницы.</li>
23 <em>Скриншот: Skillbox Media</em><ul><li>Большая - в шапке личной страницы.</li>
24 <li>Стандартная - в верхнем меню и записи в ленте.</li>
24 <li>Стандартная - в верхнем меню и записи в ленте.</li>
25 <li>Совсем крошечная - в строке "у вас столько-то подписчиков".</li>
25 <li>Совсем крошечная - в строке "у вас столько-то подписчиков".</li>
26 </ul><p>Уже получилось три состояния, но это не предел - ведь внешний вид аватарки различается в мобильной и десктопной версиях, в приложениях для Android, iOS и так далее. Отметим, что аватарка практически везде будет вложенной - в составе более крупных компонентов React.js, таких как пост, шапка, боковая панель или меню.</p>
26 </ul><p>Уже получилось три состояния, но это не предел - ведь внешний вид аватарки различается в мобильной и десктопной версиях, в приложениях для Android, iOS и так далее. Отметим, что аватарка практически везде будет вложенной - в составе более крупных компонентов React.js, таких как пост, шапка, боковая панель или меню.</p>
27 <p>В React.js есть собственные средства для управления состояниями, но на практике в средних и крупных проектах чаще используют<a>Redux</a> - сторонний менеджер состояний. Он удобнее и лучше масштабируется.</p>
27 <p>В React.js есть собственные средства для управления состояниями, но на практике в средних и крупных проектах чаще используют<a>Redux</a> - сторонний менеджер состояний. Он удобнее и лучше масштабируется.</p>
28 <p>Никаких огородов. React.js - это всего лишь способ в удобном виде представить код JavaScript и HTML, сделать его повторяемым и наглядным. Компоненты React.js пишут на особом языке - JSX, который выглядит как смесь JavaScript и HTML. Вот пример кода на этом языке:</p>
28 <p>Никаких огородов. React.js - это всего лишь способ в удобном виде представить код JavaScript и HTML, сделать его повторяемым и наглядным. Компоненты React.js пишут на особом языке - JSX, который выглядит как смесь JavaScript и HTML. Вот пример кода на этом языке:</p>
29 const name = 'Josh Perez'; const element = &lt;h1&gt;Привет, {name}&lt;/h1&gt;; ReactDOM.render( element, document.getElementById('root') );JSX-код - то, что кажется HTML-тегом &lt;h1&gt;, на самом деле элемент JSX<p>Код JSX довольно наглядный, и, кстати, то, что похоже на HTML, - вовсе не HTML :) Звучит галлюциногенно, но это просто синтаксис JSX.</p>
29 const name = 'Josh Perez'; const element = &lt;h1&gt;Привет, {name}&lt;/h1&gt;; ReactDOM.render( element, document.getElementById('root') );JSX-код - то, что кажется HTML-тегом &lt;h1&gt;, на самом деле элемент JSX<p>Код JSX довольно наглядный, и, кстати, то, что похоже на HTML, - вовсе не HTML :) Звучит галлюциногенно, но это просто синтаксис JSX.</p>
30 <p>Браузеру понимать JSX не нужно - код React.js транслируется в JavaScript, с которым знаком любой уважающий себя браузер. Для этого написанное на React.js приложение прогоняют, например, через Babel - специальную программу-транспайлер, которая переводит разные представления (то есть языки вроде JSX) в JavaScript-код.</p>
30 <p>Браузеру понимать JSX не нужно - код React.js транслируется в JavaScript, с которым знаком любой уважающий себя браузер. Для этого написанное на React.js приложение прогоняют, например, через Babel - специальную программу-транспайлер, которая переводит разные представления (то есть языки вроде JSX) в JavaScript-код.</p>
31 function getGreeting(user) { if (user) { return &lt;h1&gt;Здравствуй, {formatName(user)}!&lt;/h1&gt;; } return &lt;h1&gt;Здравствуй, незнакомец.&lt;/h1&gt;; }<p>JSX-код</p>
31 function getGreeting(user) { if (user) { return &lt;h1&gt;Здравствуй, {formatName(user)}!&lt;/h1&gt;; } return &lt;h1&gt;Здравствуй, незнакомец.&lt;/h1&gt;; }<p>JSX-код</p>
32 function getGreeting(user) { if (user) { return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, ", formatName(user), "!"); } return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, незнакомец."); }JavaScript-код после Babel<p>На первый взгляд, механика странная. Кажется, это как если бы Достоевский придумал свой собственный язык, писал на нём книги, а потом их переводили бы на русский и только после этого издавали. И это была бы хорошая аналогия - но только если бы книги Достоевского переводились на русский автоматически, а писать на новом языке было бы в несколько раз быстрее.</p>
32 function getGreeting(user) { if (user) { return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, ", formatName(user), "!"); } return /*#__PURE__*/React.createElement("h1", null, "Здравствуй, незнакомец."); }JavaScript-код после Babel<p>На первый взгляд, механика странная. Кажется, это как если бы Достоевский придумал свой собственный язык, писал на нём книги, а потом их переводили бы на русский и только после этого издавали. И это была бы хорошая аналогия - но только если бы книги Достоевского переводились на русский автоматически, а писать на новом языке было бы в несколько раз быстрее.</p>
33 <p>У React.js есть три мощных преимущества:</p>
33 <p>У React.js есть три мощных преимущества:</p>
34 <ul><li>JSX гораздо проще читать и понимать, чем JavaScript, а значит, на поддержку и отладку кода тратится гораздо меньше времени разработчиков (а это зарплаты и скорость новых релизов).</li>
34 <ul><li>JSX гораздо проще читать и понимать, чем JavaScript, а значит, на поддержку и отладку кода тратится гораздо меньше времени разработчиков (а это зарплаты и скорость новых релизов).</li>
35 <li>В нём удобно реализована система компонентов - повторяющихся частей кода, которые используются в разных условиях и обстоятельствах и меняются в зависимости от контекста.</li>
35 <li>В нём удобно реализована система компонентов - повторяющихся частей кода, которые используются в разных условиях и обстоятельствах и меняются в зависимости от контекста.</li>
36 <li>Каждый компонент зависит только от своего состояния - а значит, гораздо легче устранять ошибки в коде, если что-то не работает или работает не так, как ожидалось. То есть ошибки становятся очевидными: компонент, который работает корректно сам по себе, всегда будет работать корректно - если только ему не передать какое-то неправильное состояние.</li>
36 <li>Каждый компонент зависит только от своего состояния - а значит, гораздо легче устранять ошибки в коде, если что-то не работает или работает не так, как ожидалось. То есть ошибки становятся очевидными: компонент, который работает корректно сам по себе, всегда будет работать корректно - если только ему не передать какое-то неправильное состояние.</li>
37 </ul><p>В итоге React.js помогает сэкономить время, делает код более понятным и структурированным, даёт возможность переиспользовать большие блоки. Всё это помогает значительно снизить стоимость разработки, поддержки, обновления и отладки приложений, а также делать их значительно быстрее. К тому же, зная JavaScript и HTML, выучить его довольно просто - для основ хватит нескольких дней. React.js эффективен только на проектах с большим числом динамических страниц. Делать на React.js сайт-визитку - это перебор.</p>
37 </ul><p>В итоге React.js помогает сэкономить время, делает код более понятным и структурированным, даёт возможность переиспользовать большие блоки. Всё это помогает значительно снизить стоимость разработки, поддержки, обновления и отладки приложений, а также делать их значительно быстрее. К тому же, зная JavaScript и HTML, выучить его довольно просто - для основ хватит нескольких дней. React.js эффективен только на проектах с большим числом динамических страниц. Делать на React.js сайт-визитку - это перебор.</p>
38 <p>У React.js есть и свои конкуренты. Например, библиотеки Vue.js и Angular. На них тоже пишут пользовательские интерфейсы, у каждого есть свои плюсы и минусы. Пока что работодатели чаще ждут от разработчиков знания React.js - в марте 2023 года на hh.ru он встречался в требованиях 3300 раз, Vue.js - 1782 раза, а Angular - 1282 раза.</p>
38 <p>У React.js есть и свои конкуренты. Например, библиотеки Vue.js и Angular. На них тоже пишут пользовательские интерфейсы, у каждого есть свои плюсы и минусы. Пока что работодатели чаще ждут от разработчиков знания React.js - в марте 2023 года на hh.ru он встречался в требованиях 3300 раз, Vue.js - 1782 раза, а Angular - 1282 раза.</p>
39 <p>Согласно<a>исследованию Stack Overflow</a>, React.js был вторым по популярности веб-фреймворком в 2022 году, уступая лишь Node.js. Он даже обогнал динозавра jQuery, который разработчики уже несколько лет ненавидят (по данным того же исследования), но массово продолжают использовать. Раньше эта библиотека применялась во многих сайтах и веб-приложениях - не переписывать же их код :) Четвёртое место занял фреймворк для Node.js - Express. А конкуренты React.js - Angular и Vue.js - пятое и шестое место соответственно.</p>
39 <p>Согласно<a>исследованию Stack Overflow</a>, React.js был вторым по популярности веб-фреймворком в 2022 году, уступая лишь Node.js. Он даже обогнал динозавра jQuery, который разработчики уже несколько лет ненавидят (по данным того же исследования), но массово продолжают использовать. Раньше эта библиотека применялась во многих сайтах и веб-приложениях - не переписывать же их код :) Четвёртое место занял фреймворк для Node.js - Express. А конкуренты React.js - Angular и Vue.js - пятое и шестое место соответственно.</p>
40 <em>Скриншот: Stack Overflow</em><p>А ещё существует React Native - тоже разработка "Фейсбука"*, которую не следует путать с обычным React.js. В какой-то момент компания поняла, что на React.js пишут приложения не только для браузеров, но и для разных операционных систем. Правда, работали такие приложения довольно медленно. Чтобы решить эту проблему, в "Фейсбуке"* и создали нативную версию библиотеки.</p>
40 <em>Скриншот: Stack Overflow</em><p>А ещё существует React Native - тоже разработка "Фейсбука"*, которую не следует путать с обычным React.js. В какой-то момент компания поняла, что на React.js пишут приложения не только для браузеров, но и для разных операционных систем. Правда, работали такие приложения довольно медленно. Чтобы решить эту проблему, в "Фейсбуке"* и создали нативную версию библиотеки.</p>
41 <p>Синтаксис React Native похож на JSX, но переводится на понятный и привычный для Windows, macOS, Android и других операционных систем язык. То есть приложение становится нативным - использует стандартные для разных платформ возможности и протоколы, а не запускается в браузере. Мало того, на платформе React Native можно использовать и другие языки программирования - например, Java, Swift, Objective-C.</p>
41 <p>Синтаксис React Native похож на JSX, но переводится на понятный и привычный для Windows, macOS, Android и других операционных систем язык. То есть приложение становится нативным - использует стандартные для разных платформ возможности и протоколы, а не запускается в браузере. Мало того, на платформе React Native можно использовать и другие языки программирования - например, Java, Swift, Objective-C.</p>
42 <p>Получить доступ к React.js можно двумя способами.</p>
42 <p>Получить доступ к React.js можно двумя способами.</p>
43 <p>Это самый простой способ. Можно поиграться с библиотекой в онлайн-песочницах<a>CodePen</a>и <a>CodeSandBox</a>или скачать<a>HTML-файл с шаблоном</a>c GitHub. После этого свой код можно прогнать через<a>Babel</a> - тоже онлайн, чтобы не устанавливать лишние приложения.</p>
43 <p>Это самый простой способ. Можно поиграться с библиотекой в онлайн-песочницах<a>CodePen</a>и <a>CodeSandBox</a>или скачать<a>HTML-файл с шаблоном</a>c GitHub. После этого свой код можно прогнать через<a>Babel</a> - тоже онлайн, чтобы не устанавливать лишние приложения.</p>
44 <p>Инсталляция и настройка полноценного окружения React.js требует больше времени и подходит для более продвинутых пользователей.</p>
44 <p>Инсталляция и настройка полноценного окружения React.js требует больше времени и подходит для более продвинутых пользователей.</p>
45 <p>Для этого предварительно нужно<a>установить Node.js</a> - это среда, которая позволяет запускать JS-код как серверное приложение.</p>
45 <p>Для этого предварительно нужно<a>установить Node.js</a> - это среда, которая позволяет запускать JS-код как серверное приложение.</p>
46 <p>Затем скачайте пакет create-react-app с помощью npm:</p>
46 <p>Затем скачайте пакет create-react-app с помощью npm:</p>
47 npm i -g create-react-app<p>Когда модуль установится, создайте шаблон приложения, выполнив следующую команду:</p>
47 npm i -g create-react-app<p>Когда модуль установится, создайте шаблон приложения, выполнив следующую команду:</p>
48 create-react-app my-first-app<p>Если всё будет ОК, Node.js в конце сообщения выведет Happy hacking!.</p>
48 create-react-app my-first-app<p>Если всё будет ОК, Node.js в конце сообщения выведет Happy hacking!.</p>
49 <p>Запустите приложение:</p>
49 <p>Запустите приложение:</p>
50 cd my-first-app npm start<p>С помощью команды cd мы перешли в папку проекта, а командой start запустили локальный сервер разработки http://localhost:3000/. В результате вы должны увидеть в браузере такую красоту:</p>
50 cd my-first-app npm start<p>С помощью команды cd мы перешли в папку проекта, а командой start запустили локальный сервер разработки http://localhost:3000/. В результате вы должны увидеть в браузере такую красоту:</p>
51 <em>Изображение: Skillbox Media</em><p>Напишем на React.js веб-версию бессмертного хита - игры "крестики-нолики". Весь код, за исключением стилей, будем писать в файле App.js в папке src.</p>
51 <em>Изображение: Skillbox Media</em><p>Напишем на React.js веб-версию бессмертного хита - игры "крестики-нолики". Весь код, за исключением стилей, будем писать в файле App.js в папке src.</p>
52 <p>Сначала импортируем модуль React, вебхук из неё и библиотеку ReactDOM для рендеринга компонентов:</p>
52 <p>Сначала импортируем модуль React, вебхук из неё и библиотеку ReactDOM для рендеринга компонентов:</p>
53 import React, { useState } from "react"; import ReactDOM from "react-dom";<p>Логику игры будем писать в компоненте App, который уже содержит код. Можете его полностью удалить - он нам не пригодится:</p>
53 import React, { useState } from "react"; import ReactDOM from "react-dom";<p>Логику игры будем писать в компоненте App, который уже содержит код. Можете его полностью удалить - он нам не пригодится:</p>
54 function App() { /*Здесь будет логика приложения*/ };<p>С помощью useState создадим хук, который возвращает массив squares, - он будет хранить клетки игрового поля:</p>
54 function App() { /*Здесь будет логика приложения*/ };<p>С помощью useState создадим хук, который возвращает массив squares, - он будет хранить клетки игрового поля:</p>
55 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); };<p>squares будет инициализироваться в начале игры как массив из девяти пустых элементов, а его состояние при необходимости будет изменять функция setSquares.</p>
55 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); };<p>squares будет инициализироваться в начале игры как массив из девяти пустых элементов, а его состояние при необходимости будет изменять функция setSquares.</p>
56 <p>Создадим второй хук для хранения очереди (кто ходит следующим: X или 0):</p>
56 <p>Создадим второй хук для хранения очереди (кто ходит следующим: X или 0):</p>
57 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); };<p>По умолчанию состояние устанавливается в true - это значит, что первыми будут ходить крестики. Функция setXIsNext переключает очереди игроков.</p>
57 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); };<p>По умолчанию состояние устанавливается в true - это значит, что первыми будут ходить крестики. Функция setXIsNext переключает очереди игроков.</p>
58 <p>На каждом ходе надо проверять, не определился ли победитель. Для этого напишем функцию calculateWinner:</p>
58 <p>На каждом ходе надо проверять, не определился ли победитель. Для этого напишем функцию calculateWinner:</p>
59 const calculateWinner = (squares) =&gt; { 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 &lt; lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] &amp;&amp; squares[a] === squares[b] &amp;&amp; squares[a] === squares[c]) { return squares[a]; } } return null; };<p>В calculateWinner передаётся массив с текущими значениями клеток игрового поля. Во внутреннем массиве lines содержатся выигрышные комбинации полей. Функция перебирает их, подставляя на место индексов входного массива, и, если все три значения совпадут, возвращает победителя (X или 0) или null, если победителя нет.</p>
59 const calculateWinner = (squares) =&gt; { 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 &lt; lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] &amp;&amp; squares[a] === squares[b] &amp;&amp; squares[a] === squares[c]) { return squares[a]; } } return null; };<p>В calculateWinner передаётся массив с текущими значениями клеток игрового поля. Во внутреннем массиве lines содержатся выигрышные комбинации полей. Функция перебирает их, подставляя на место индексов входного массива, и, если все три значения совпадут, возвращает победителя (X или 0) или null, если победителя нет.</p>
60 <p>Значение calculateWinner хранится в переменной winner:</p>
60 <p>Значение calculateWinner хранится в переменной winner:</p>
61 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); const winner = calculateWinner(squares); };<p>Теперь нужно наладить взаимодействие игроков с интерфейсом. Оно будет происходить через функцию handleClick, которая вызывается при клике на игровое поле. Она создаёт копию массива квадратов, проверяет, может ли текущий игрок сделать ход в выбранный квадрат, и изменяет массив квадратов и состояние игрока (чередует ходы), если ход был возможен.</p>
61 function App() { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); const winner = calculateWinner(squares); };<p>Теперь нужно наладить взаимодействие игроков с интерфейсом. Оно будет происходить через функцию handleClick, которая вызывается при клике на игровое поле. Она создаёт копию массива квадратов, проверяет, может ли текущий игрок сделать ход в выбранный квадрат, и изменяет массив квадратов и состояние игрока (чередует ходы), если ход был возможен.</p>
62 function App() { { /* Остальной код */ const handleClick = (i) =&gt; { const squaresCopy = [...squares]; if (winner || squaresCopy[i]) return; squaresCopy[i] = xIsNext ? "X" : "O"; setSquares(squaresCopy); setXIsNext(!xIsNext); };<p>Следующая функция будет рисовать клетки поля, которые на самом деле являются обыкновенными HTML-кнопками. renderSquare принимает номер квадрата и возвращает кнопку, на которую можно кликнуть и сделать ход:</p>
62 function App() { { /* Остальной код */ const handleClick = (i) =&gt; { const squaresCopy = [...squares]; if (winner || squaresCopy[i]) return; squaresCopy[i] = xIsNext ? "X" : "O"; setSquares(squaresCopy); setXIsNext(!xIsNext); };<p>Следующая функция будет рисовать клетки поля, которые на самом деле являются обыкновенными HTML-кнопками. renderSquare принимает номер квадрата и возвращает кнопку, на которую можно кликнуть и сделать ход:</p>
63 const renderSquare = (i) =&gt; { return ( &lt;button className="square" onClick={() =&gt; handleClick(i)}&gt; {squares[i]} &lt;/button&gt; ); };<p>Пусть программа выводит статус игры над полем. Если есть победитель, то статус будет "Победитель: X" или "Победитель: 0". Если же победителя нет - "Следующий игрок: X" или "Следующий игрок: 0".</p>
63 const renderSquare = (i) =&gt; { return ( &lt;button className="square" onClick={() =&gt; handleClick(i)}&gt; {squares[i]} &lt;/button&gt; ); };<p>Пусть программа выводит статус игры над полем. Если есть победитель, то статус будет "Победитель: X" или "Победитель: 0". Если же победителя нет - "Следующий игрок: X" или "Следующий игрок: 0".</p>
64 const status = winner ? `Winner: ${winner}` : `Next player: ${xIsNext ? "X" : "O"}`;<p>Теперь пропишем JSX-элементы, которые будет возвращать функция App, - они и будут отображаться на странице:</p>
64 const status = winner ? `Winner: ${winner}` : `Next player: ${xIsNext ? "X" : "O"}`;<p>Теперь пропишем JSX-элементы, которые будет возвращать функция App, - они и будут отображаться на странице:</p>
65 &lt;div className="game-field"&gt; &lt;div className="status"&gt;{status}&lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} &lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} &lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} &lt;/div&gt; &lt;/div&gt;<p>Сначала выводится статус игры, затем с помощью renderSquare рисуется каждая клетка игрового поля.</p>
65 &lt;div className="game-field"&gt; &lt;div className="status"&gt;{status}&lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} &lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} &lt;/div&gt; &lt;div className="board-row"&gt; {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} &lt;/div&gt; &lt;/div&gt;<p>Сначала выводится статус игры, затем с помощью renderSquare рисуется каждая клетка игрового поля.</p>
66 <p>Чтобы игровой интерфейс выглядел красиво и клетки при нажатии на них не вылезали за пределы своих рядов, нужно настроить стили страницы. Сохраните в файле styles.css следующий код:</p>
66 <p>Чтобы игровой интерфейс выглядел красиво и клетки при нажатии на них не вылезали за пределы своих рядов, нужно настроить стили страницы. Сохраните в файле styles.css следующий код:</p>
67 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; }<p>Подключите файл директивой import:</p>
67 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; }<p>Подключите файл директивой import:</p>
68 import "./styles.css";<p>И добавьте в каждый ряд (элементы div с атрибутом className="board-row") класс flex.</p>
68 import "./styles.css";<p>И добавьте в каждый ряд (элементы div с атрибутом className="board-row") класс flex.</p>
69 <p><strong>Обратите внимание:</strong>слово<strong>class</strong>в JavaScript зарезервировано для других целей, поэтому имя класса элемента в нём указывают с помощью аналога -<strong>className</strong>.</p>
69 <p><strong>Обратите внимание:</strong>слово<strong>class</strong>в JavaScript зарезервировано для других целей, поэтому имя класса элемента в нём указывают с помощью аналога -<strong>className</strong>.</p>
70 <p>Весь код проекта:</p>
70 <p>Весь код проекта:</p>
71 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) =&gt; { const squaresCopy = [...squares]; if (winner || squaresCopy[i]) return; squaresCopy[i] = xIsNext ? "X" : "O"; setSquares(squaresCopy); setXIsNext(!xIsNext); }; const renderSquare = (i) =&gt; { return ( &lt;button className="square" onClick={() =&gt; handleClick(i)}&gt; {squares[i]} &lt;/button&gt; ); }; const status = winner ? `Winner: ${winner}` : `Next player: ${xIsNext ? "X" : "O"}`; return ( &lt;div className="game-field"&gt; &lt;div className="status"&gt;{status}&lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} &lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} &lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} &lt;/div&gt; &lt;/div&gt; ); }; const calculateWinner = (squares) =&gt; { 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 &lt; lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] &amp;&amp; squares[a] === squares[b] &amp;&amp; squares[a] === squares[c]) { return squares[a]; } } return null; };<p>А вот как должна выглядеть игра в окне браузера:</p>
71 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) =&gt; { const squaresCopy = [...squares]; if (winner || squaresCopy[i]) return; squaresCopy[i] = xIsNext ? "X" : "O"; setSquares(squaresCopy); setXIsNext(!xIsNext); }; const renderSquare = (i) =&gt; { return ( &lt;button className="square" onClick={() =&gt; handleClick(i)}&gt; {squares[i]} &lt;/button&gt; ); }; const status = winner ? `Winner: ${winner}` : `Next player: ${xIsNext ? "X" : "O"}`; return ( &lt;div className="game-field"&gt; &lt;div className="status"&gt;{status}&lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} &lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} &lt;/div&gt; &lt;div className="board-row flex"&gt; {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} &lt;/div&gt; &lt;/div&gt; ); }; const calculateWinner = (squares) =&gt; { 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 &lt; lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] &amp;&amp; squares[a] === squares[b] &amp;&amp; squares[a] === squares[c]) { return squares[a]; } } return null; };<p>А вот как должна выглядеть игра в окне браузера:</p>
72 <em>Изображение: Skillbox Media</em><p>React.js - довольно простая библиотека, хотя, как и в любом деле, здесь есть нюансы. Например, вебхуки, однонаправленная передача данных, callback-функции, виртуальный DOM, методы жизненного цикла. Написать новый "Фейсбук"* или "Инстаграм"* на React.js не так-то просто, но всё равно это очень дружественная библиотека.</p>
72 <em>Изображение: Skillbox Media</em><p>React.js - довольно простая библиотека, хотя, как и в любом деле, здесь есть нюансы. Например, вебхуки, однонаправленная передача данных, callback-функции, виртуальный DOM, методы жизненного цикла. Написать новый "Фейсбук"* или "Инстаграм"* на React.js не так-то просто, но всё равно это очень дружественная библиотека.</p>
73 <p>Обязательно ознакомьтесь с документацией проекта и учебником по синтаксису JSX<a>на официальном сайте</a>React.js. Начните с Hello, World! и смело экспериментируйте в CodePen - так советуют авторы гайда.</p>
73 <p>Обязательно ознакомьтесь с документацией проекта и учебником по синтаксису JSX<a>на официальном сайте</a>React.js. Начните с Hello, World! и смело экспериментируйте в CodePen - так советуют авторы гайда.</p>
74 <p>Как обычно, легче всего осваивать технологию на реальных задачах - например, поставьте себе цель скопировать часть интерфейса "Фейсбука"* или "Инстаграма"*. Почему бы и нет?</p>
74 <p>Как обычно, легче всего осваивать технологию на реальных задачах - например, поставьте себе цель скопировать часть интерфейса "Фейсбука"* или "Инстаграма"*. Почему бы и нет?</p>
75 <p>* Решением суда запрещена "деятельность компании Meta Platforms Inc. по реализации продуктов - социальных сетей Facebook и Instagram на территории Российской Федерации по основаниям осуществления экстремистской деятельности".</p>
75 <p>* Решением суда запрещена "деятельность компании Meta Platforms Inc. по реализации продуктов - социальных сетей Facebook и Instagram на территории Российской Федерации по основаниям осуществления экстремистской деятельности".</p>
76 <a>Курс с трудоустройством: "Профессия Фронтенд-разработчик + ИИ" Узнать о курсе</a>
76 <a>Курс с трудоустройством: "Профессия Фронтенд-разработчик + ИИ" Узнать о курсе</a>