Сегодня, в десятой части перевода учебного курса по React, мы предлагаем вам выполнить практическое задание по работе со свойствами компонентов и по их стилизации.
→ Часть 1: обзор курса, причины популярности React, ReactDOM и JSX
→ Часть 2: функциональные компоненты
→ Часть 3: файлы компонентов, структура проектов
→ Часть 4: родительские и дочерние компоненты
→ Часть 5: начало работы над TODO-приложением, основы стилизации
→ Часть 6: о некоторых особенностях курса, JSX и JavaScript
→ Часть 7: встроенные стили
→ Часть 8: продолжение работы над TODO-приложением, знакомство со свойствами компонентов
→ Часть 9: свойства компонентовЗанятие 20. Практикум. Свойства компонентов, стилизация
▍Задание
Создайте новый проект React-приложения.
Выведите на странице приложения компонент
App, код которого должен находиться в отдельном файле.Компонент App должен выводить 5 компонентов
Joke, содержащих анекдоты. Выведите эти компоненты так, как вам хочется.Каждый компонент
Jokeдолжен принимать и обрабатывать свойствоquestion, для основной части анекдота, и свойствоpunchLine— для его ключевой фразы.▍Дополнительное задание
Некоторые анекдоты целиком состоят из ключевой фразы. Например: «It’s hard to explain puns to kleptomaniacs because they always take things literally». Подумайте над тем, как компонент
Jokeможет вывести лишь переданное ему свойствоpunchLine, в том случае, если свойствоquestionне задано. Поэкспериментируйте со стилизацией компонентов.▍Решение
Основное задание
Файл
index.jsбудет выглядеть вполне привычно:import React from "react"import ReactDOM from "react-dom"import App from "./App"ReactDOM.render(<App />,document.getElementById("root"))
Вот код файлаApp.js:import React from "react"import Joke from "./Joke"function App() {return (<div><Jokequestion="What's the best thing about Switzerland?"punchLine="I don't know, but the flag is a big plus!"/><Jokequestion="Did you hear about the mathematician who's afraid of negative numbers?"punchLine="He'll stop at nothing to avoid them!"/><Jokequestion="Hear about the new restaurant called Karma?"punchLine="There’s no menu: You get what you deserve."/><Jokequestion="Did you hear about the actor who fell through the floorboards?"punchLine="He was just going through a stage."/><Jokequestion="Did you hear about the claustrophobic astronaut?"punchLine="He just needed a little space."/></div>)}export default AppОбратите внимание на то, что, так как файл компонента
Jokeрасположен в той же папке, что и файл компонентаApp, мы импортируем его командойimport Joke from "./Joke". ИзAppмы возвращаем несколько элементов, поэтому весь вывод нужно обернуть в некий тег, например — в тег<div>. Экземплярам компонента мы передаём свойстваquestionиpunchLine.
Вот код файлаJoke.js:import React from "react"function Joke(props) {return (<div><h3>Question: {props.question}</h3><h3>Answer: {props.punchLine}</h3><hr/></div>)}export default JokeЗдесь, при объявлении функции
Joke, мы указываем параметрprops. Напомним, что именно такое имя используется по сложившейся традиции. На самом деле оно может быть любым, но лучше называть его именноprops.
Из компонента мы возвращаем несколько элементов — поэтому они заключены в тег<div>. С помощью конструкцийprops.questionиprops.punchLineмы обращаемся к свойствам, переданным экземпляру компонента при его создании. Эти свойства становятся свойствами объектаprops. Они заключены в фигурные скобки из-за того, что JavaScript-код, используемый в JSX-разметке, нужно оформлять фигурными скобками. Иначе система примет имена переменных за обычный текст. После пары элементов<h3>, в одном из которых выводится основной текст анекдота, а в другой — его ключевая фраза, находится элемент<hr/>, описывающий горизонтальную линию. Такие линии будут выводиться после каждого анекдота, разделяя их.
Вот как выглядит проект приложения в VSCode.
Приложение в VSCode
Вот страница приложения.
Страница приложения в браузере
Дополнительное задание
Напомним, что основная цель дополнительного задания заключается в том, чтобы организовать правильный вывод анекдотов, которые целиком состоят из ключевой фразы. Это выражается в том, что, при создании экземпляра компонента
Joke, ему передают лишь свойствоpunchLine, а свойствоquestionне передают. Создание экземпляра подобного компонента выглядит так:<JokepunchLine="It’s hard to explain puns to kleptomaniacs because they always take things literally."/>Если поместить этот код в верхнюю часть кода, возвращаемого компонентом
App, то страница приложения примет следующий вид.
Неправильно сформированная страница приложения
Очевидно, проблема тут заключается в том, что, хотя компоненту не передано свойства
question, он выводит текст, предваряющий основную часть каждого анекдота, после которого ничего уже не выводится.
Забегая вперёд отметим, что в будущих частях курса мы поговорим об условном рендеринге. С помощью этого подхода к рендерингу можно эффективно решать задачи, подобные нашей. Пока же мы попытаемся воспользоваться средствами стилизации страниц. А именно, сделаем так, чтобы, если компоненту не передаётся свойствоquestion, соответствующий фрагмент возвращаемой им JSX-разметки не отображался бы на странице. Вот полный код компонентаJoke, в котором реализован один из возможных подходов решения нашей проблемы средствами CSS:import React from "react"function Joke(props) {return (<div><h3 style={{display: props.question ? "block" : "none"}}>Question: {props.question}</h3><h3>Answer: {props.punchLine}</h3><hr/></div>)}export default JokeПервому элементу
<h3>мы назначаем стиль, который определяется в процессе создания экземпляра компонента на основе наличия в объекте свойстваprops.question. Если это свойство в объекте есть, элемент принимает стильdisplay: blockи выводится на страницу, если нет —display: noneи на страницу не выводится. К тому же эффекту приведёт и использование такой конструкции:<h3 style={{display: !props.question && "none"}}>Question: {props.question}</h3>Здесь стиль
display: noneназначается элементу в том случае, если у объектаpropsнет свойстваquestion, в противном случае свойствуdisplayне назначается ничего.
Теперь страница приложения в браузере будет выглядеть так, как показано ниже.
Правильная обработка компонентом ситуации, в которой ему не передают свойство question
Можно заметить, что все элементы, формируемые компонентом
Joke, выглядят одинаково. Подумаем над тем, как выделить те из них, которым передаётся лишь свойствоpunchLine. Решим эту задачу, используя встроенные стили, и тот подход, который мы рассмотрели выше. Вот обновлённый код компонентаJoke:import React from "react"function Joke(props) {return (<div><h3 style={{display: !props.question && "none"}}>Question: {props.question}</h3><h3 style={{color: !props.question && "#888888"}}>Answer: {props.punchLine}</h3><hr/></div>)}export default JokeА вот как выглядит то, что теперь выводится на страницу приложения.
Стилизация элемента, который отличается от других
Теперь, после того, как мы поработали над компонентом
Joke, он стал более универсальным и лучше подходящим для повторного использования.Итоги
На этом практическом занятии мы занимались отработкой навыков передачи компонентам свойств. Если проанализировать код приведённого здесь примера, можно заметить, что для вывода нескольких похожих блоков разметки приходится постоянно писать повторяющиеся фрагменты JSX-кода. На следующем занятии мы поговорим о том, как стандартными средствами JavaScript автоматизировать формирование подобных страниц, заодно разделив разметку и данные.
JavaScript





