Создание компонента
ReactDOM.render принимает react-компонент (далее буду называть просто "компонент") и DOM-элемент, в который мы хотим "примонтировать" наше приложение.
<h1>Hello, world!</h1> - как ни странно, это примитивный компонент.
Пока ничего интересного, но давайте представим такой псевдо-код:
1
var photos = ['images/cat.jpg','images/dog.jpg','images/owl.jpg']
2
3
ReactDOM.render(
4
<App>
5
<Photos photos=photos />
6
<LastNews />
7
<Comments />
8
</App>,
9
document.getElementById('root')
10
);
Copied!
Что примечательного в данном псевдо-коде? Он очень хорошо читается, ведь очевидно, что наше приложение (App) отображает: фото (кошка, собака, сова), новости и комментарии.
Хочу вас обрадовать, React.js код выглядит практически так же. Он отлично читается, так как деление на компоненты позволяет отлично структурировать код.
Давайте создадим примитивный компонент:
index.html
1
<!DOCTYPE html>
2
...
3
<body>
4
<div id="root"></div>
5
<script type="text/babel">
6
7
const App = () => {
8
return <p>Всем привет, я компонент App</p>
9
}
10
11
ReactDOM.render(
12
<App />,
13
document.getElementById('root')
14
);
15
16
</script>
17
18
</body>
19
</html>
Copied!
Что примечательного? Мы скрыли в <App /> разметку. Да, в этом примере это одна строка и чувство эйфории отсутствует, но то ли еще будет! Пока запомним, что если мы хотим отрисовать в JSX компонент, то мы обязательно должны называть и вызывать его с Большой буквы.
Смотрим на результирующий html-код:
Мы создали компонент с помощью функции. Но компоненты, можно создавать и с помощью class. Убьем сразу нескольких зайцев:
  • изучим как создавать компоненты с помощью class
  • как передать css-стиль
  • как отрисовать сразу несколько компонентов
index.html
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset="UTF-8" />
5
<title>React [RU] Tutorial v2</title>
6
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
7
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
8
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
9
10
<style>
11
.red {
12
color: #FF0000;
13
}
14
</style>
15
</head>
16
<body>
17
<div id="root"></div>
18
<script type="text/babel">
19
20
const App = () => {
21
return <p>Всем привет, я компонент App</p>
22
}
23
24
class BigApp extends React.Component {
25
render() {
26
return (
27
<div>
28
<h1>Я компонент, BigApp</h1>
29
<p className='red'>Компоненты можно вкладывать друг в друга.</p>
30
<App/>
31
</div>
32
)
33
}
34
}
35
36
ReactDOM.render(
37
<BigApp />,
38
document.getElementById('root')
39
);
40
41
</script>
42
43
</body>
44
</html>
Copied!
Синтаксис:
1
class (название) extends (что будем наследовать)
Copied!
так же позволяет создать компонент. Здесь стоит отметить, что если компонент создан с помощью класса, то JSX разметка пишется внутри метода render. Это ключевой метод, в котором мы указываем, что будет отображаться пользователю на странице.
Компоненты созданные с помощью class, называются statefull компоненты (то есть, компоненты с состоянием), а компоненты созданные с помощью функции - stateless component (то есть, компоненты без состояния). Зачем такое деление - узнаем позже.
В примере мы добавили стиль для параграфа, через className, а не через class, как мы привыкли делать это. Почему? Потому что, мы находимся внутри JSX-синтаксиса, в котором html и js идут вперемешку, а слово class зарезервировано в javascript.
Напоследок отмечу, что мы с легкостью смогли вложить один компонент в другой.
В разметке все как мы и ожидали. Однако, я уже вижу читателей, кому не нравится лишний div.

Каждый компонент должен возвращать один узел

Рассмотрим проблему с div'ом. Как написано в заголовке, мы должны возвращать всегда один dom-узел. Попробуем удалить div:
index.html
1
<script type="text/babel">
2
3
const App = () => {
4
return <p>Всем привет, я компонент App</p>
5
}
6
7
class BigApp extends React.Component {
8
render() {
9
// убрали div
10
return (
11
<h1>Я компонент, BigApp</h1>
12
<p className='red'>Компоненты можно вкладывать друг в друга.</p>
13
<App/>
14
)
15
}
16
}
17
18
ReactDOM.render(
19
<BigApp />,
20
document.getElementById('root')
21
);
22
23
</script>
Copied!
Ошибка: jsx-элементы должны быть обернуты в один тэг. Что делать, если не хочется городить еще один div? Ответ: React.Fragment
Все довольны. Разницы особо нет, как вам больше нравится, так и пишите, но помните: все что вы возвращаете в render методе или в return у stateless-компонента должно быть обернуто в один тэг / React.Fragment.
Давайте разовьем идею: научим BigApp отображать новости. Для этого, нам потребуется создать компонент <News /> и вложить его в BigApp.
index.html
1
const App = () => {
2
return <p>Всем привет, я компонент App</p>
3
}
4
5
const News = () => {
6
return <p>К сожалению, новостей нет</p>
7
}
8
9
class BigApp extends React.Component {
10
render() {
11
return (
12
<React.Fragment>
13
<h1>Я компонент, BigApp</h1>
14
<p className='red'>Компоненты можно вкладывать друг в друга.</p>
15
<App />
16
<News />
17
</React.Fragment>
18
)
19
}
20
}
21
22
ReactDOM.render(
23
<BigApp />,
24
document.getElementById('root')
25
);
Copied!
Давайте, вновь взглянем на код и поищем примечательные места.
Во-первых - мы никак не изменили код внутри ReactDOM.render. Мы просто вложили в BigApp еще один компонент.
Во-вторых, как уже было сказано - компонент <BigApp /> содержит в себе компонент <News />, словно это просто дочерний <div></div> элемент.
В-третьих, наш компонент <News /> такой же примитивный, как и App, поэтому мы создали его через функцию (а не через class).
Задачка на понимание происходящего: Удалите компонет <BigApp/>, оставьте <App /> (не переписывая его на statefull-компонент). В <App /> отображайте <News />. Так же создайте компонент <Comments /> и сделайте, чтобы он отображался после новостей. Текст компонента: "Нет новостей - комментировать нечего."
Решение для задачи всегда публикуется ниже по тексту, и обычно содержит сначала подсказки, а потом код всего решения. Здесь подсказок нет.
Решение:
index.html
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset="UTF-8" />
5
<title>React [RU] Tutorial v2</title>
6
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
7
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
8
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
9
10
<style>
11
.red {
12
color: #FF0000;
13
}
14
</style>
15
</head>
16
<body>
17
<div id="root"></div>
18
<script type="text/babel">
19
20
const News = () => {
21
return <p>К сожалению, новостей нет</p>
22
}
23
24
const Comments = () => {
25
return <p>Нет новостей - комментировать нечего.</p>
26
}
27
28
const App = () => {
29
return (
30
<React.Fragment>
31
<News />
32
<Comments />
33
</React.Fragment>
34
)
35
}
36
37
ReactDOM.render(
38
<App />,
39
document.getElementById('root')
40
);
41
42
</script>
43
44
</body>
45
</html>
Copied!
Прежде чем переходить к следующему уроку, предлагаю вам установить react devtools (плагин для хрома, плагин для мозилы).
Так как мы разрабатываем просто в файлике index.html, нужно активировать опцию в плагине (в хроме выглядит так):
После установки и настройки откройте вкладку React в консоли разработчика.
Пытливый читатель уже заметил окошечко "Props". Ок, об этом и поговорим в следующей главе.
Исходный код на данный момент.
Last modified 1yr ago