Хабрахабр

[Перевод] Учебный курс по React, часть 21: второе занятие и практикум по условному рендерингу

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

image

→ Часть 1: обзор курса, причины популярности React, ReactDOM и JSX
→ Часть 2: функциональные компоненты
→ Часть 3: файлы компонентов, структура проектов
→ Часть 4: родительские и дочерние компоненты
→ Часть 5: начало работы над TODO-приложением, основы стилизации
→ Часть 6: о некоторых особенностях курса, JSX и JavaScript
→ Часть 7: встроенные стили
→ Часть 8: продолжение работы над TODO-приложением, знакомство со свойствами компонентов
→ Часть 9: свойства компонентов
→ Часть 10: практикум по работе со свойствами компонентов и стилизации
→ Часть 11: динамическое формирование разметки и метод массивов map
→ Часть 12: практикум, третий этап работы над TODO-приложением
→ Часть 13: компоненты, основанные на классах
→ Часть 14: практикум по компонентам, основанным на классах, состояние компонентов
→ Часть 15: практикумы по работе с состоянием компонентов
→ Часть 16: четвёртый этап работы над TODO-приложением, обработка событий
→ Часть 17: пятый этап работы над TODO-приложением, модификация состояния компонентов
→ Часть 18: шестой этап работы над TODO-приложением
→ Часть 19: методы жизненного цикла компонентов
→ Часть 20: первое занятие по условному рендерингу
→ Часть 21: второе занятие и практикум по условному рендерингу

Занятие 37. Условный рендеринг, часть 2

→ Оригинал

Экспериментировать будем со стандартным проектом, созданным средствами create-react-app, в файле App.js которого находится следующий код: На сегодняшнем занятии по условному рендерингу мы поговорим об использовании логического оператора && (И).

import React, from "react" class App extends Component { constructor() { super() this.state = { unreadMessages: [ "Call your mom!", "New spam email available. All links are definitely safe to click." ] } } render() { return ( <div> <h2>You have {this.state.unreadMessages.length} unread messages!</h2> </div> ) }
} export default App

Сейчас приложение выглядит в браузере так, как показано ниже.

Страница приложения в браузере

Для того, чтобы в результате вычисления подобного выражения было бы возвращено true, оно должно выглядеть как true && true. Возможно, вы уже пользовались оператором && в конструкциях наподобие true && false (что даёт false). Если обрабатывается выражение вида false && false, то сразу будет возвращено false, без проверки правой части выражения. При обработке таких выражений JavaScript определяет, является ли их левая часть истинной, и, если это так, просто возвращает то, что находится в их правой части. С его помощью можно либо вернуть что-то, что будет выведено на экран, либо не возвращать ничего. В результате оператор && можно использовать в условном рендеринге.

Проанализируем код учебного приложения.

Каждая строка в этом массиве представляет собой непрочитанное сообщение. В состоянии компонента App хранится массив строк unreadMessages. Если же этот массив будет пустым, то есть в нём не будет ни одного элемента, то приложение выведет на страницу то, что показано ниже. На страницу выводится количество непрочитанных сообщений, определяемое на основе длины массива.

Приложение информирует нас о том, что непрочитанных сообщений нет

Для того чтобы добиться такого эффекта, достаточно привести массив к такому виду: unreadMessages: [].

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

render() { return ( <div> { this.state.unreadMessages.length > 0 ? <h2>You have {this.state.unreadMessages.length} unread messages!</h2> : null } </div> )
}

Теперь в том случае, если массив unreadMessages пуст, на страницу не будет выводиться ничего. Но представленный здесь код можно упростить благодаря использованию оператора &&. Вот как это будет выглядеть:

render() { return ( <div> { this.state.unreadMessages.length > 0 && <h2>You have {this.state.unreadMessages.length} unread messages!</h2> } </div> )
}

Если в массиве что-то есть — на страницу выводится правая часть выражения. Если массив пуст — на страницу не выводится ничего.

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

Занятие 38. Практикум. Условный рендеринг

→ Оригинал

▍Задание

Вот код функционального компонента App, который хранится в файле App.js стандартного проекта, созданного с помощью create-react-app.

import React from "react" function App() { return ( <div> Code goes here </div> )
} export default App

Вам нужно сделать следующее:

  1. Преобразуйте код компонента так, чтобы оснастить его состоянием.
  2. Сделайте так, чтобы в состоянии компонента хранились бы сведения о том, «вошёл» ли пользователь в систему или нет (в этом упражнении «вход» в систему и «выход» из неё означает лишь изменение соответствующего значения, хранящегося в состоянии).
  3. Добавьте на страницу, которую формирует компонент, кнопку, которая позволяет пользователю входить в систему и выходить из неё.
    1. Это — дополнительное задание. Сделайте так, чтобы, если пользователь не вошёл в систему, на кнопке выводилась бы надпись LOG IN, а если вошёл — надпись LOG OUT.
  4. Выведите на странице, формируемой компонентом, надпись Logged in в том случае, если пользователь вошёл в систему, и Logged out в том случае, если не вошёл.

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

▍Подсказки

Для выполнения этого задания нужно вспомнить многое из того, о чём мы говорили на предыдущих занятиях. Начнём с того, что компонент, который может иметь состояние, должен быть компонентом, который основан на классе. У этого компонента должен быть конструктор. В состоянии компонента можно хранить логическое свойство, например, его можно назвать isLoggedIn, значение которого, true или false, указывает на то, вошёл пользователь в систему или нет. Для того чтобы кнопка, которую нужно добавить на страницу, генерируемую приложением, могла бы выполнять свои функции, ей понадобится обработчик события onClick. Для того чтобы выводить разные тексты, опираясь на изменяющееся значение состояния, нужно будет прибегнуть к технологии условного рендеринга.

▍Решение

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

Здесь же мы, в конструкторе компонента, описываем его первоначальное состояние, которое содержит свойство isLoggedIn, установленное в значение false. Вот как будет выглядеть код функционального компонента, преобразованного в компонент, основанный на классе.

import React from "react" class App extends React.Component { constructor() { super() this.state = { isLoggedIn: false } } render() { return ( <div> Code goes here </div> ) }
} export default App

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

import React from "react" class App extends React.Component { constructor() { super() this.state = { isLoggedIn: false } this.handleClick = this.handleClick.bind(this) } handleClick() { console.log("I'm working!") } render() { return ( <div> <button onClick={this.handleClick}>LOG IN</button> </div> ) }
} export default App

При нажатии на кнопку LOG IN в консоль попадает текст I’m working!.

Для этого в обработчике щелчка по кнопке нужно будет вызвать функцию this.setState(), которую можно использовать двумя способами. Теперь вспомним о том, что нам надо, чтобы при щелчке по кнопке свойство isLoggedIn, хранящееся в состоянии, менялось бы с true на false и наоборот. Второй вариант её использования предусматривает передачу ей функции, которая принимает предыдущее состояние компонента и формирует новое, возвращая, опять же, объект. А именно, ей можно предоставить, в виде объекта, новое представление того, что должно содержаться в состоянии. Вот что у нас получилось на данном этапе работы. Мы поступим именно так.

import React from "react" class App extends React.Component { constructor() { super() this.state = { isLoggedIn: false } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(prevState => { return { isLoggedIn: !prevState.isLoggedIn } }) } render() { return ( <div> <button onClick={this.handleClick}>LOG IN</button> </div> ) }
} export default App

Тут можно было бы воспользоваться конструкцией if-else, но мы просто преобразовываем значение true в значение false, а значение false в значение true с использованием логического оператора ! (НЕ).

Поэтому сейчас мы решим дополнительную задачу задания №3. Пока у нас нет механизма, который, основываясь на том, что хранится в состоянии, позволял бы влиять на внешний вид приложения. Для того чтобы этого добиться, можно объявить в методе render() переменную, значение которой, LOG IN или LOG OUT, зависит от того, что хранится в состоянии. А именно, сделаем так, чтобы надпись на кнопке менялась бы в зависимости от состояния компонента. Вот как это выглядит. Это значение потом можно использовать в качестве текста кнопки.

import React from "react" class App extends React.Component { constructor() { super() this.state = { isLoggedIn: false } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(prevState => { return { isLoggedIn: !prevState.isLoggedIn } }) } render() { let buttonText = this.state.isLoggedIn ? "LOG OUT" : "LOG IN" return ( <div> <button onClick={this.handleClick}>{buttonText}</button> </div> ) }
} export default App

Теперь займёмся четвёртой частью задания. Будем выводить на страницу текст, зависящий от того, вошёл пользователь в систему или нет. Собственно говоря, учитывая всё то, что уже присутствует в коде компонента, решить эту задачу очень просто. Ниже представлен готовый код файла App.js.

import React from "react" class App extends React.Component { constructor() { super() this.state = { isLoggedIn: false } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(prevState => { return { isLoggedIn: !prevState.isLoggedIn } }) } render() { let buttonText = this.state.isLoggedIn ? "LOG OUT" : "LOG IN" let displayText = this.state.isLoggedIn ? "Logged in" : "Logged out" return ( <div> <button onClick={this.handleClick}>{buttonText}</button> <h1>{displayText}</h1> </div> ) }
} export default App

Вот как выглядит приложение в браузере.

Страница приложения в браузере

Щелчок по кнопке LOG IN, изображённой на предыдущем рисунке, меняет состояние приложения, после чего на кнопке выводится надпись LOG OUT, а на странице выводится текст, информирующий пользователя о том, что он вошёл в систему.

Итоги

Сегодня мы продолжили разговор об условном рендеринге, рассмотрели использование оператора && и выполнили практическое задание, затрагивающее множество изученных нами механизмов. В следующий раз вас ждёт продолжение работы над Todo-приложением и новая тема.

Уважаемые читатели! Справились ли вы с сегодняшним практическим заданием?

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть