ReactDOM.render принимает react-компонент (далее буду называть просто "компонент") и DOM-элемент, в который мы хотим "примонтировать" наше приложение.
<h1>Hello, world!</h1>
- как ни странно, это примитивный компонент.
Пока ничего интересного, но давайте представим такой псевдо-код:
var photos = ['images/cat.jpg','images/dog.jpg','images/owl.jpg'] ReactDOM.render( <App> <Photos photos=photos /> <LastNews /> <Comments /> </App>, document.getElementById('root') );
Что примечательного в данном псевдо-коде? Он очень хорошо читается, ведь очевидно, что наше приложение (App) отображает: фото (кошка, собака, сова), новости и комментарии.
Хочу вас обрадовать, React.js код выглядит практически так же. Он отлично читается, так как деление на компоненты позволяет отлично структурировать код.
Давайте создадим примитивный компонент:
index.html
<!DOCTYPE html> ... <body> <div id="root"></div> <script type="text/babel"> const App = () => { return <p>Всем привет, я компонент App</p> } ReactDOM.render( <App />, document.getElementById('root') ); </script> </body> </html>
Что примечательного? Мы скрыли в <App />
разметку. Да, в этом примере это одна строка и чувство эйфории отсутствует, но то ли еще будет! Пока запомним, что если мы хотим отрисовать в JSX компонент, то мы обязательно должны называть и вызывать его с Большой буквы.
Смотрим на результирующий html-код:
Мы создали компонент с помощью функции. Но компоненты, можно создавать и с помощью class
. Убьем сразу нескольких зайцев:
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>React [RU] Tutorial v2</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/[email protected]/babel.min.js"></script> <style> .red { color: #FF0000; } </style> </head> <body> <div id="root"></div> <script type="text/babel"> const App = () => { return <p>Всем привет, я компонент App</p> } class BigApp extends React.Component { render() { return ( <div> <h1>Я компонент, BigApp</h1> <p className='red'>Компоненты можно вкладывать друг в друга.</p> <App/> </div> ) } } ReactDOM.render( <BigApp />, document.getElementById('root') ); </script> </body> </html>
Синтаксис:
class (название) extends (что будем наследовать)
так же позволяет создать компонент. Здесь стоит отметить, что если компонент создан с помощью класса, то JSX разметка пишется внутри метода render. Это ключевой метод, в котором мы указываем, что будет отображаться пользователю на странице.
Компоненты созданные с помощью class, называются statefull компоненты (то есть, компоненты с состоянием), а компоненты созданные с помощью функции - stateless component (то есть, компоненты без состояния). Зачем такое деление - узнаем позже.
В примере мы добавили стиль для параграфа, через className
, а не через class
, как мы привыкли делать это. Почему? Потому что, мы находимся внутри JSX-синтаксиса, в котором html и js идут вперемешку, а слово class зарезервировано в javascript.
Напоследок отмечу, что мы с легкостью смогли вложить один компонент в другой.
В разметке все как мы и ожидали. Однако, я уже вижу читателей, кому не нравится лишний div
.
Рассмотрим проблему с div'ом. Как написано в заголовке, мы должны возвращать всегда один dom-узел. Попробуем удалить div:
index.html
<script type="text/babel"> const App = () => { return <p>Всем привет, я компонент App</p> } class BigApp extends React.Component { render() { // убрали div return ( <h1>Я компонент, BigApp</h1> <p className='red'>Компоненты можно вкладывать друг в друга.</p> <App/> ) } } ReactDOM.render( <BigApp />, document.getElementById('root') ); </script>
Ошибка: jsx-элементы должны быть обернуты в один тэг. Что делать, если не хочется городить еще один div? Ответ: React.Fragment
Все довольны. Разницы особо нет, как вам больше нравится, так и пишите, но помните: все что вы возвращаете в render методе или в return у stateless-компонента должно быть обернуто в один тэг / React.Fragment.
Давайте разовьем идею: научим BigApp отображать новости. Для этого, нам потребуется создать компонент <News />
и вложить его в BigApp.
index.html
const App = () => { return <p>Всем привет, я компонент App</p> } const News = () => { return <p>К сожалению, новостей нет</p> } class BigApp extends React.Component { render() { return ( <React.Fragment> <h1>Я компонент, BigApp</h1> <p className='red'>Компоненты можно вкладывать друг в друга.</p> <App /> <News /> </React.Fragment> ) } } ReactDOM.render( <BigApp />, document.getElementById('root') );
Давайте, вновь взглянем на код и поищем примечательные места.
Во-первых - мы никак не изменили код внутри ReactDOM.render. Мы просто вложили в BigApp еще один компонент.
Во-вторых, как уже было сказано - компонент <BigApp />
содержит в себе компонент <News />
, словно это просто дочерний <div></div>
элемент.
В-третьих, наш компонент <News />
такой же примитивный, как и App, поэтому мы создали его через функцию (а не через class).
Задачка на понимание происходящего: Удалите компонет <BigApp/>
, оставьте <App />
(не переписывая его на statefull-компонент). В <App />
отображайте <News />
. Так же создайте компонент <Comments />
и сделайте, чтобы он отображался после новостей. Текст компонента: "Нет новостей - комментировать нечего."
Решение для задачи всегда публикуется ниже по тексту, и обычно содержит сначала подсказки, а потом код всего решения. Здесь подсказок нет.
Решение:
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>React [RU] Tutorial v2</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/[email protected]/babel.min.js"></script> <style> .red { color: #FF0000; } </style> </head> <body> <div id="root"></div> <script type="text/babel"> const News = () => { return <p>К сожалению, новостей нет</p> } const Comments = () => { return <p>Нет новостей - комментировать нечего.</p> } const App = () => { return ( <React.Fragment> <News /> <Comments /> </React.Fragment> ) } ReactDOM.render( <App />, document.getElementById('root') ); </script> </body> </html>
Прежде чем переходить к следующему уроку, предлагаю вам установить react devtools (плагин для , плагин для ).
Так как мы разрабатываем просто в файлике index.html, нужно активировать опцию в плагине (в хроме выглядит так):
После установки и настройки откройте вкладку React в консоли разработчика.
Пытливый читатель уже заметил окошечко "Props". Ок, об этом и поговорим в следующей главе.
на данный момент.