Использование state
Вернемся от теории к практике: давайте покликаем по ссылкам-кнопочкам, поизменяем свойства компонентов...
Упс, не выйдет! Как вы помните, свойства (this.props) следует использовать только для чтения, а для динамических свойств нужно использовать так называемое "состояние" (state).
Итак, встречайте - this.state ;)
Так как мне нужно в этом разделе сохранить минимум теории и больше практики, сразу перейдем к делу. Предлагаю вместе решить следующую задачу: у новости есть ссылка "подробнее", по клику на которую - бинго, текст новости целиком.
Начнем с изменения данных:
1
const myNews = [
2
{
3
id: 1,
4
author: 'Саша Печкин',
5
text: 'В четверг, четвертого числа...',
6
bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'
7
},
8
{
9
id: 2,
10
author: 'Просто Вася',
11
text: 'Считаю, что $ должен стоить 35 рублей!',
12
bigText: 'А евро 42!'
13
},
14
{
15
id: 3,
16
author: 'Max Frontend',
17
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35',
18
bigText: 'А евро опять выше 70.'
19
},
20
{
21
id: 4,
22
author: 'Гость',
23
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru',
24
bigText: 'Еще есть группа VK, telegram и канал на youtube! Вся инфа на сайте, не реклама!'
25
}
26
];
Copied!
Затем, научимся отображать полный текст новости сразу после вводного текста:
1
class Article extends React.Component {
2
render() {
3
const { author, text, bigText } = this.props.data // вытащили bigText из даты
4
return (
5
<div className='article'>
6
<p className='news__author'>{author}:</p>
7
<p className='news__text'>{text}</p>
8
<p className='news__big-text'>{bigText}</p>
9
</div>
10
)
11
}
12
}
13
14
Article.propTypes = {
15
data: PropTypes.shape({
16
author: PropTypes.string.isRequired,
17
text: PropTypes.string.isRequired,
18
bigText: PropTypes.string.isRequired // добавили propTypes для bigText
19
})
20
}
Copied!
Опять же, больше ничего изменять не нужно. Данные корректно отобразятся.
Проверим...
news with readmore
Отлично, можно продолжать работу: добавим ссылку - "подробнее". Приведу фрагмент кода:
1
...
2
return (
3
<div className='article'>
4
<p className='news__author'>{author}:</p>
5
<p className='news__text'>{text}</p>
6
<a href="#" className='news__readmore'>Подробнее</a>
7
<p className='news__big-text'>{bigText}</p>
8
</div>
9
)
10
...
Copied!
Проверьте и если все ок - мы готовы к работе с состоянием компонента.

Начальное состояние

С состоянием (state) можно работать только в statefull компонентах (class)
Если вы определяете какое-то изменяемое свойство в компоненте, необходимо указать начальное состояние (в терминологии react.js - initial state). Для этого, у компонента нужно просто определить свойство state:
1
class Article extends React.Component {
2
state = {
3
visible: false, // определили начальное состояние
4
}
5
render() {
6
const { author, text, bigText } = this.props.data
7
return (
8
<div className='article'>
9
<p className='news__author'>{author}:</p>
10
<p className='news__text'>{text}</p>
11
<a href="#" className='news__readmore'>Подробнее</a>
12
<p className='news__big-text'>{bigText}</p>
13
</div>
14
)
15
}
16
}
Copied!
Посмотрим в консоли на вкладке React:
news initial state
В состоянии (в state) появилось свойство. Будем использовать его в момент render'а.
Формализуем задачу:
  • если значение this.state.visible === false -> рисуй "подробнее", не рисуй "большой текст";
  • если же this.state.visible === true -> не рисуй "подробнее", рисуй большой текст;
Будем использовать логическое выражение внутри JSX, значит - фигурные скобки, и внутри js-выражение.
1
class Article extends React.Component {
2
state = {
3
visible: false,
4
}
5
render() {
6
const { author, text, bigText } = this.props.data
7
const { visible } = this.state // вытащили visible из this.state
8
return (
9
<div className='article'>
10
<p className='news__author'>{author}:</p>
11
<p className='news__text'>{text}</p>
12
{ /* если не visible, то показывай */
13
!visible && <a href="#" className='news__readmore'>Подробнее</a>
14
}
15
{ /* если visible, то показывай */
16
visible && <p className='news__big-text'>{bigText}</p>
17
}
18
</div>
19
)
20
}
21
}
Copied!
Мы использовали одну и ту же переменную состояния в двух местах когда описывали обычное javascript выражение. Если вы не знакомы с И / ИЛИ, то рекомендую почитать у Кантора (Логические операторы).
Обратите внимание, для написания комментариев не понадобились дополнительные фигурные скобки, так как мы уже находились внутри "выражения" внутри JSX.
Можете проверить в браузере, и покликать на чекбокс внутри state зоны. Шаблон уже будет реагировать. А мы продолжим делать все это по-человечески, чтобы можно было кликать на "подробнее".

Обработка кликов - onClick

Чтобы обработать клик, нам необходимо указать атрибут onClick у элемента.
В качестве обработчика у нас будет функция, которая изменяет состояние. Для изменения состояния, нужно обязательно использовать метод setState, а не перезаписывать значение переменной в this.state напрямую.
1
class Article extends React.Component {
2
state = {
3
visible: false,
4
}
5
handleReadMoreClck = (e) => { // добавили метод
6
e.preventDefault()
7
this.setState({ visible: true })
8
}
9
render() {
10
const { author, text, bigText } = this.props.data
11
const { visible } = this.state
12
return (
13
<div className='article'>
14
<p className='news__author'>{author}:</p>
15
<p className='news__text'>{text}</p>
16
{ /* добавили onClick */
17
!visible && <a onClick={this.handleReadMoreClck} href="#" className='news__readmore'>Подробнее</a>
18
}
19
{
20
visible && <p className='news__big-text'>{bigText}</p>
21
}
22
</div>
23
)
24
}
25
}
Copied!
Проверьте в браузере, кликните на ссылку "подробнее".
Каждый компонент <Article /> имеет свое состояние! Поэтому, при клике на подробнее в одном из компонентов, только его состояние изменяется, и только у этой новости отображается полный текст.
news last readmore
Итого:
Для сохранения динамических свойств, используется состояние (state) компонента.
Для обработки клика, используется свойство onClick + функция-обработчик. Существуют и другие стандартные события, которые работают по такому же принципу. Полный список здесь. Мы будем знакомиться с ними по мере необходимости.
Для изменения состояния, используется метод setState, который принимает объект с аргументами, которые нужно изменить. Например, у нас есть состояние:
1
...
2
state = {
3
visible: false,
4
rating: 0,
5
eshe_odno_svoistvo: 'qweqwe'
6
}
7
...
Copied!
Чтобы изменить рейтинг, нужно написать следующий setState:
1
this.setState({rating: 100500})
Copied!
Чтобы изменить все три свойства:
1
this.setState({
2
rating: 100500,
3
visible: true,
4
eshe_odno_svoistvo: 'привет'
5
})
Copied!
Так же у setState есть возможность указать callback функцию, которая будет вызвана после того, как новое состояние "установится".
1
...
2
readmoreClick: function(e) {
3
e.preventDefault();
4
this.setState({ visible: true }, () => {
5
alert('Состояние изменилось');
6
});
7
},
8
...
Copied!
Еще setState есть возможность... (на самом деле есть, но с нас пока хватит).
Посмотреть полный список возможностей setState можно в документации.
Исходный код на данный момент.
Last modified 1yr ago