мини-тест по содержанию урока (5 минут)
В предыдущем уроке мы научились писать несложные компоненты на React, использовать props
и state
компонентов, обрабатывать события и компоновать компоненты на странице. В данном уроке мы узнаем еще больше о компонентах, изучим их жизненный цикл, научимся использовать refs
, работать с дочерними компонентами и DOM.
В React есть относительно немного методов жизненного цикла, но все они очень мощные. React дает вам все необходимые методы для контроля свойств и состояния приложения в процессе его жизни.
Есть всего 4 сценария, когда методы жизненного цикла могут быть использованы:
- Инициализация компонента
- Изменение его параметров (
props
) - Изменение его состояния (вызов
setState
) - Удаление компонента
Инициализация компонента (первый render)
При первом render
компонента методы жизненного цикла будут вызваны в таком порядке:
Изменение параметров (props
)
Когда от родительского компонента приходят измененные параметры, последовательность вызова методов жизненного цикла такая:
Изменение состояния (вызов setState
)
Когда в компоненте изменяется состояние, то методы жизненного цикла вызываются в таком порядке:
Удаление компонента
Перед удаление компонента из DOM будет вызван один-единственный метод сomponentWillUnmount
getDefaultProps
Вызывается единожды при инициализации класса. Отвечает за значения параметров по умолчанию.
getDefaultProps: function() {
return {
name: ‘’,
age: 0
};
}
getInitialState
Создан для определения начального состояния компонента.
getInitialState: function() {
return {
isOpened: true
};
}
componentWillMount
Вызывается один раз прямо перед тем, как состоится первый render
компонента. Вызов setState
в рамках данного метода дополнительного рендера не вызовет.
componentWillMount: function() {
// ...
}
componentDidMount
Вызывается один раз прямо сразу после того, как состоялся первый render
компонента.
componentDidMount: function() {
// компонент уже находится в DOM
// здесь можно уже взаимодействовать с DOM напрямую
// например, использовать jQuery или какие-то сторонние библиотеки
}
componentWillReceiveProps
Вызывается каждый раз, когда компонент получает новые параметры. Не вызывается для первого рендера. Вызов setState
в рамках данного метода дополнительного рендера не вызовет.
componentWillReceiveProps: function(nextProps) {
// в nextProps содержится объект с новыми параметрами
// старые параметры можно получить использование this.props
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}
shouldComponentUpdate
Вызывается при изменении параметров или состояния. Возвращает true
(если изменение должно вызвать перерисовку компонента) или false
(если изменение не влияет на отображение компонента).
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.id !== this.props.id;
}
Если shouldComponentUpdate
возвращает false
, то метод render()
будет пропущен до следующего изменения параметров или состояния. По умолчанию (если не определен), всегда возвращает true
. Может быть использован для улучшения бустродействия приложения (чтобы избежать лишних перерисовок), особенно если используется огромное количество компонентов.
componentWillUpdate
Вызывается перед вызовом метода render()
при изменении параметров или состояния компонента.
componentWillUpdate: function(nextProps, nextState) {
// в nextProps содержится объект с новыми параметрами
// в nextState содержится объект с измененным состоянием
}
!!! Не используйте setState()
в этом методе! Так у вас может произойти зацикливание!
componentDidUpdate
Вызывается сразу после вызова метода render()
при изменении параметров или состояния компонента.
componentDidUpdate: function(prevProps, prevState) {
// в prevProps содержится объект с предыдущими параметрами
// в prevState содержится объект с состоянием до изменения
// измененные параметры и состояние могут быть получены через this.props и this.state
}
Произведенные изменения уже отображены в DOM дереве. Обычно, в данном методе производят какие-то операции с DOM елементами согласно изменениям.
!!! Не используйте setState()
в этом методе! Так у вас может произойти зацикливание!
componentWillUnmount
Вызывается перед тем, как компонент будет удален из DOM.
componentWillUnmount: function() {
// обычно, в данном методе происходит некая уборка за компонентом
// остановка таймеров, удаление ссылок на DOM елементы и т.д.
}
Весь жизненный цикл компонента можно представить в виде такой схемы
Иногда вместо того, чтобы писать так:
<Article author="Vasya Pupkin" text="Here is article itself" />
Очень хочется написать так:
<Article author="Vasya Pupkin"> Here is article itself </Article>
Для таких случаев существуют this.props.children
. В компоненте Article
можно просто обратиться к ним для получения всего содержимого между открывающимся и закрывающимся тегами.
var Acricle = React.createClass({
render: function() {
return (
<div>
<p>{this.props.children}</p>
by {this.props.author}
</div>
);
}
});
// для удобства работы со стилями они представлены в виде объекта,
// а не строки, объект со стилями передается в атрибут style
var divStyle = {
color: 'white',
height: 50, // можно не писать 'px', а использовать числа
backgroundImage: 'url(' + imgUrl + ')', // вместо background-image
WebkitTransition: 'all',// все префиксы с заглавной буквы
msTransition: 'all' // кроме ms-*
};
ReactDOM.render(
<div style={divStyle}>Hello World!</div>,
mountNode
);
Атрибут ref
может быть callback функцией, которая будет немедленно исполнена, после того как компонент будет установлен.
Указанный компонент будет передан в качестве параметра, и функция обратного вызова может сразу использовать компонент, или сохранить ссылки для дальнейшего использования.
Стоит отметить что, при прикреплении ref
на компонент DOM, такой как тег <div />
вы получите DOM узел обратно; в то время как при при присоединении ref
к составному компоненту такому как <MyComponent />
, вы получете экземпляр React класса.
В последнем случае вы можете вызывать методы этого компонента, если таковые будут определены.
// для удобства работы с элементами DOM дерева в методе render(),
// мы используем refs(ссылка на элемент DOM),
// чтобы использовать свойства и методы полученного объекта
var MyComponent = React.createClass({
handleClick: function() {
this.input.focus();
},
render: function() {
return (
<div>
<input type="text" ref={ i => this.input = i } />
<button onClick={this.handleClick}>Focus</button>
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
React так же поддерживает использование строки (вместо обратного вызова):
<input ref="myInput" />
Но стоит отметить тот факт что в документации разработчики утверждают что string refs
считаются устаревшими.
Рефы обратного вызова являются предпочтительными.
Если на странице есть 100 (или 1000) различных элементов, на которых вы назначили обработчики события onClick
— React вместо того, чтобы назначать обработчик каждому, поставит только один обработчик на их общего предка, а там, уже с помощью всплытия, поймет на каком именно потомке произошло событие и обработает его. Такой подход упрощает инициализацию и экономит память.
- В каком порядке и какие вызываются методы жизненного цикла при первом render'е компонента, при изменении параметров, при изменении состояния, при удалении компонента?
- Вызовет ли дополнительный render использование
setState()
в методеcomponentWillReceiveProps
? - Как влияет метод
shouldComponentUpdate
наrender
? - Какой из методов жизненного цикла следует использовать для снятия события с window?
- Как обратиться к тому, что лежит между тегами
<Component> Some more JSX here </Component>
из компонентаComponent
? - Зачем нужны
refs
и как к ним обращаться? - Чем отличается определение inline стилей для компонента в React от их использования в html? Как передать inline стили в компонент?
- Зачем для событий используется
bind
? Когда его следует использовать? - Если вы на 1000 компонентов повесите 1000 событий, значит ли это, что будет в действительности объявлено 1000 событий? Почему?
Установка node и npm
- Для Windows: скачать .msi установщик
- Для Linux: запустить
curl -L https://npmjs.org/install.sh | sh
в терминале - Для Mac: скачать .pkg установщик или
brew install node
, если используете Homebrew
Установка и использование http-server
- документация на npm
- чтобы установить пишем:
npm install http-server -g
- для того, чтобы поднять сервер:
http-server -p 8081
Cсылки:
- Сайт nodejs — https://nodejs.org
- NPM — https://www.npmjs.com
- Документация NPM — https://docs.npmjs.com/
- Документация http-server — https://www.npmjs.com/package/http-server
- Библиотека Masonry — http://masonry.desandro.com/
Задание 1: Сделать выбор цвета для заметки
Уровень сложности: низкий
При создании новой заметки реализовать выбор ее цвета. Можно выбирать из всего спектра (<input type="color" />
) или использовать только 5–7 ваших любимых цветов (как в Google Keep).
Задание 2: Таймер
Уровень сложности: средний
Нужно усовершенствовать написанный таймер добавлением в него кнопок "Пауза", "Старт" и "Возобновить".
Задание 3: Поиск по заметкам
Уровень сложности: средний
Добавить на страницу поле для поиска (желательно выделить в отдельный компонент). По мере ввода, должны отфильтровываться заметки, которые соответствуют введенному значению.
Задание 4: To-do list
Уровень сложности: высокий
Написать список задач. Пользователь может добавить новую задачу, отметить ее как выполненную (просто вычеркнуть ее из списка) и фильтры "Все", "Завершенные" и "Новые". Задачи должны сохраняться в localStorage.
Если есть вопросы пишите сюда