Pull to refresh
2924.7
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

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

Reading time 8 min
Views 9.1K
Original author: Bob Ziroll
Сегодня, в переводе следующей части учебного курса по 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: второе занятие и практикум по условному рендерингу
Часть 22: седьмой этап работы над TODO-приложением, загрузка данных из внешних источников
Часть 23: первое занятие по работе с формами
Часть 24: второе занятие по работе с формами
Часть 25: практикум по работе с формами
Часть 26: архитектура приложений, паттерн Container/Component
Часть 27: курсовой проект

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


Оригинал

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

import React, {Component} 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 && false (что даёт false). Для того, чтобы в результате вычисления подобного выражения было бы возвращено true, оно должно выглядеть как true && true. При обработке таких выражений JavaScript определяет, является ли их левая часть истинной, и, если это так, просто возвращает то, что находится в их правой части. Если обрабатывается выражение вида false && false, то сразу будет возвращено false, без проверки правой части выражения. В результате оператор && можно использовать в условном рендеринге. С его помощью можно либо вернуть что-то, что будет выведено на экран, либо не возвращать ничего.

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

В состоянии компонента 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!.

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

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-приложением и новая тема.

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

Tags:
Hubs:
+28
Comments 2
Comments Comments 2

Articles

Information

Website
ruvds.com
Registered
Founded
Employees
11–30 employees
Location
Россия
Representative
ruvds