Сегодня мы предлагаем вам выполнить два практических занятия по работе с состоянием компонентов. В частности, выполняя сегодняшние задания, вы сможете не только лучше усвоить концепцию свойств, но и позаниматься отладкой React-приложений, в которых имеются ошибки.
→ Часть 1: обзор курса, причины популярности React, ReactDOM и JSX
→ Часть 2: функциональные компоненты
→ Часть 3: файлы компонентов, структура проектов
→ Часть 4: родительские и дочерние компоненты
→ Часть 5: начало работы над TODO-приложением, основы стилизации
→ Часть 6: о некоторых особенностях курса, JSX и JavaScript
→ Часть 7: встроенные стили
→ Часть 8: продолжение работы над TODO-приложением, знакомство со свойствами компонентов
→ Часть 9: свойства компонентов
→ Часть 10: практикум по работе со свойствами компонентов и стилизации
→ Часть 11: динамическое формирование разметки и метод массивов map
→ Часть 12: практикум, третий этап работы над TODO-приложением
→ Часть 13: компоненты, основанные на классах
→ Часть 14: практикум по компонентам, основанным на классах, состояние компонентовЗанятие 27. Практикум. Состояние компонентов, отладка
▍Задание
Проанализируйте представленный ниже код класса
App
из файлаApp.js
стандартного React-приложения, созданного средствамиcreate-react-app
. Этот код неполон, в нём есть ошибки.import React from "react"
class App extends Component() {
return (
<div>
<h1>{this.state.name}</h1>
<h3><font color="#3AC1EF">▍{this.state.age} years old</font></h3>
</div>
)
}
export default App
У компонента
App
, основанного на классе, нет конструктора, его состояние не инициализировано, но при формировании того, что он возвращает, подразумевается наличие у него состояния с некими данными.
Ваша задача заключается в том, чтобы привести этот код в работоспособное состояние.
Если вы столкнётесь с неким неизвестным вам сообщением об ошибке — не спешите заглядывать в решение. Попытайтесь самостоятельно, например, внимательно вчитавшись в код и поискав сведения о проблеме в интернете, выяснить причину ошибки и её исправить. Отладка кода — ценнейший навык, который обязательно пригодиться вам при работе над реальными проектами.▍Решение
Тело класса похоже на тело функционального компонента. В нём имеется лишь команда
return
, но в компонентах, основанных на классах, эта команда используется в методеrender()
, а не в теле класса. Исправим это.import React from "react"
class App extends Component() {
render() {
return (
<div>
<h1>{this.state.name}</h1>
<h3><font color="#3AC1EF">▍{this.state.age} years old</font></h3>
</div>
)
}
}
export default App
Если продолжить анализ кода, поглядывая на сообщения об ошибках, выводимые в браузере, можно понять, что хотя конструкция
class App extends Component
выглядит вполне нормально, с тем, к чему мы обращаемся по имениComponent
, всё ещё что-то не так. Проблема заключается в том, что в команде импорта,import React from "react"
, мы импортируем в проект лишьReact
, но неComponent
. То есть, нам надо либо отредактировать эту команду, приведя её к видуimport React, {Component} from "react"
, тогда при создании класса мы сможем воспользоваться уже существующим кодом, либо переписать объявление класса в таком виде:class App extends React.Component
. Мы остановимся на первом варианте. Теперь код компонента выглядит так:import React, {Component} from "react"
class App extends Component() {
render() {
return (
<div>
<h1>{this.state.name}</h1>
<h3><font color="#3AC1EF">▍{this.state.age} years old</font></h3>
</div>
)
}
}
export default App
Правда, на этом проблемы не заканчиваются. Приложение не работает, в браузере появляется сообщение об ошибке
TypeError: Cannot set property 'props' of undefined
, нам сообщают, что что-то не так с первой строкой объявления класса.
Дело тут в том, что при объявлении компонента, который, как мы уже поняли, является компонентом, который основан на классе, после имени родительского класса стоит пара круглых скобок. Они тут не нужны, это не функциональный компонент, поэтому от них мы избавимся. Теперь код приложения оказывается более или менее работоспособным, компонент, основанный на классе, уже не выглядит совершенно неправильным, но система продолжает сообщать нам об ошибках. Теперь сообщение об ошибке выглядит так:TypeError: Cannot read property 'name' of null
. Очевидно, оно относится к попытке использования данных, хранящихся в состоянии компонента, которое пока не инициализировано. Поэтому теперь мы создадим конструктор класса, не забыв вызвать в нёмsuper()
, и инициализируем состояние компонента, добавив в него значения, с которыми компонент пытается работать.
Вот готовый рабочий код компонентаApp
:import React, {Component} from "react"
class App extends Component {
constructor() {
super()
this.state = {
name: "Sally",
age: 13
}
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
<h3><font color="#3AC1EF">▍{this.state.age} years old</font></h3>
</div>
)
}
}
export default App
Вот как будет выглядеть страница приложения в браузере.
Страница приложения в браузере
Занятие 28. Практикум. Состояние компонентов, работа с данными, хранящимися в состоянии
На этом практическом занятии у вас будет ещё один шанс поработать с состоянием компонентов.
▍Задание
Ниже приведён код функционального компонента. Взяв его за основу, сделайте следующее:
Преобразуйте его так, чтобы у компонента было бы состояние.
В состоянии компонента должно присутствовать свойство
isLoggedIn
, хранящее логическое значениеtrue
, если пользователь вошёл в систему, иfalse
— если нет (в нашем случае никаких механизмов «входа в систему» здесь нет, соответствующее значение нужно установить вручную, при инициализации состояния).Постарайтесь сделать так, чтобы, если пользователь в систему вошёл, компонент выводил бы текст
You are currently logged in
, а если нет — то текстYou are currently logged out
. Это задание является необязательным, если у вас возникнут трудности при его выполнении, можете, например, поискать идеи в интернете.Вот код файла
App.js
:import React from "react"
function App() {
return (
<div>
<h1>You are currently logged (in/out)</h1>
</div>
)
}
export default App
▍Решение
В нашем распоряжении имеется функциональный компонент. Для того чтобы оснастить его состоянием, его надо преобразовать в компонент, основанный на классе и инициализировать его состояние. Вот как выглядит код преобразованного компонента:
import React from "react"
class App extends React.Component {
constructor() {
super()
this.state = {
isLoggedIn: true
}
}
render() {
return (
<div>
<h1>You are currently logged (in/out)</h1>
</div>
)
}
}
export default App
Проверим работоспособность приложения.
Приложение в браузере
На самом деле, если вы самостоятельно дошли до этого момента, это значит, что вы усвоили данный в курсе материал, посвящённый компонентам, основанным на классах и состоянию компонентов. Теперь займёмся необязательным заданием.
В сущности, то, что нужно сделать для выполнения этого задания, мы будем обсуждать на занятии, которое посвящено условному рендерингу, так что здесь мы немного забегаем вперёд. Итак, мы собираемся объявить и инициализировать переменную, которая будет содержать строкуin
илиout
в зависимости от того, что именно хранится в свойстве состоянияisLoggedIn
. Работать с этой переменной мы будем в методеrender()
, сначала анализируя данные и записывая в неё нужное значение, а потом используя её в возвращаемом компонентом JSX-коде. Вот что у нас в итоге получилось:import React from "react"
class App extends React.Component {
constructor() {
super()
this.state = {
isLoggedIn: true
}
}
render() {
let wordDisplay
if (this.state.isLoggedIn === true) {
wordDisplay = "in"
} else {
wordDisplay = "out"
}
return (
<div>
<h1>You are currently logged {wordDisplay}</h1>
</div>
)
}
}
export default App
Обратите внимание на то, что переменная
wordDisplay
— это обычная локальная переменная, объявленная в методеrender()
, поэтому для обращения к ней внутри этого метода достаточно лишь указать её имя.
Вот как теперь будет выглядеть страница приложения:
Страница приложения в браузере
Свойство состояния
isLoggedIn
установлено в значениеtrue
, поэтому на странице выводится текстYou are currently logged in
. Для вывода текстаYou are currently logged out
нужно поменять, в коде компонента, значениеisLoggedIn
наfalse
.
Надо отметить, что эту задачу можно решить и другими способами. Но код, который у нас получился, понятен и работоспособен, поэтому мы остановимся на нём, хотя, например, учитывая то, чтоisLoggedIn
— логическая переменная, условиеif (this.state.isLoggedIn === true)
можно переписать какif (this.state.isLoggedIn)
.Итоги
Сегодня вы попрактиковались в работе с состоянием компонентов, в частности, исправляли ошибки в коде, перерабатывали функциональный компонент в компонент, основанный на классах, занимались условным рендерингом. В следующий раз вас ждёт ещё одна практическая работа и новая тема.

JavaScript