Использование state
ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в telegram канале или twitter
На канале так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы, присоединяйтесь!
Использование state
Вернемся от теории к практике, покликаем по ссылкам-кнопочкам, поизменяем свойства компонентов...
Упс, простите. Как вы помните, свойства (this.props) следует использовать только для чтения, а для динамических свойств нужно использовать так называемое "состояние" (state).
Итак, встречайте - this.state ;)
Так как мне нужно в этом разделе сохранить минимум теории и больше практики, сразу перейдем к делу. Предлагаю вместе решить следующую задачу: у новости есть ссылка "подробнее", по клику на которую - бинго, текст новости целиком.
Начнем с изменения данных:
var my_news = [
{
author: 'Саша Печкин',
text: 'В четчерг, четвертого числа...',
bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'
},
{
author: 'Просто Вася',
text: 'Считаю, что $ должен стоить 35 рублей!',
bigText: 'А евро 42!'
},
{
author: 'Гость',
text: 'Бесплатно. Скачать. Лучший сайт - http://localhost:3000',
bigText: 'На самом деле платно, просто нужно прочитать очень длинное лицензионное соглашение'
}
];
Затем, научимся отображать полный текст новости сразу после вводного текста:
var Article = React.createClass({
propTypes: {
data: React.PropTypes.shape({
author: React.PropTypes.string.isRequired,
text: React.PropTypes.string.isRequired,
bigText: React.PropTypes.string.isRequired
})
},
render: function() {
var author = this.props.data.author,
text = this.props.data.text,
bigText = this.props.data.bigText;
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
<p className='news__big-text'>{bigText}</p>
</div>
)
}
});
Опять же, больше ничего изменять не нужно. Данные корректно отобразятся.
Проверим...

Отлично, можно продолжать работу: добавим ссылку - "подробнее". Приведу фрагмент кода:
...
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
<a href="#" className='news__readmore'>Подробнее</a>
<p className='news__big-text'>{bigText}</p>
</div>
)
...
Проверьте и если все ок - мы готовы к работе с состоянием компонента.
getInitialState
Если вы определяете какое-то изменяемое свойство в компоненте, необходимо указать начальное состояние (в терминологии react.js - initial state). Для этого, у компонента указывается метод getInitialState:
var Article = React.createClass({
propTypes: {
data: React.PropTypes.shape({
author: React.PropTypes.string.isRequired,
text: React.PropTypes.string.isRequired,
bigText: React.PropTypes.string.isRequired
})
},
getInitialState: function() {
return {
visible: false
};
},
render: function() {
var author = this.props.data.author,
text = this.props.data.text,
bigText = this.props.data.bigText;
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
<a href="#" className='news__readmore'>Подробнее</a>
<p className='news__big-text'>{bigText}</p>
</div>
)
}
});
Посмотрим в консоли на вкладке React:

В состоянии (в state) появилось свойство. Будем использовать его в момент render'а.
var Article = React.createClass({
propTypes: {
data: React.PropTypes.shape({
author: React.PropTypes.string.isRequired,
text: React.PropTypes.string.isRequired,
bigText: React.PropTypes.string.isRequired
})
},
getInitialState: function() {
return {
visible: false
};
},
render: function() {
var author = this.props.data.author,
text = this.props.data.text,
bigText = this.props.data.bigText,
visible = this.state.visible; // считываем значение переменной из состояния компонента
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
{/* для ссылки readmore: не показывай ссылку, если visible === true */}
<a href="#" className={'news__readmore ' + (visible ? 'none': '')}>Подробнее</a>
{/* для большо текста: не показывай текст, если visible === false */}
<p className={'news__big-text ' + (visible ? '': 'none')}>{bigText}</p>
</div>
)
}
});
Можно проверить в браузере, я лишь заострю внимание, что мы вновь использовали выражение в качестве значения css-класса у элемента (не забывайте пробел), а так же использовали одну и ту же переменную состояния в двух местах: теперь, когда мы научимся изменять состояние по клику (чуть ниже), если показывается большой текст - ссылка подробнее, наоборот, прячется.
Обработка кликов - onClick
Чтобы обработать клик, нам необходимо указать атрибут onClick у элемента.
В качестве обработчика у нас будет функция, которая изменяет состояние. Для изменения состояния, нужно обязательно использовать метод setState, а не просто перезаписывать значение переменной.
var Article = React.createClass({
propTypes: {
data: React.PropTypes.shape({
author: React.PropTypes.string.isRequired,
text: React.PropTypes.string.isRequired,
bigText: React.PropTypes.string.isRequired
})
},
getInitialState: function() {
return {
visible: false
};
},
readmoreClick: function(e) {
e.preventDefault();
this.setState({visible: true});
},
render: function() {
var author = this.props.data.author,
text = this.props.data.text,
bigText = this.props.data.bigText,
visible = this.state.visible;
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
<a href="#" onClick={this.readmoreClick} className={'news__readmore ' + (visible ? 'none': '')}>Подробнее</a>
<p className={'news__big-text ' + (visible ? '': 'none')}>{bigText}</p>
</div>
)
}
});
Проверьте в браузере, кликните на ссылку "подробнее".
--
Итого:
Для сохранения динамических свойств, используется состояние (state) компонента.
Для обработки клика, используется свойство onClick + функция-обработчик. Существуют и другие стандартные события, которые работают по такому же принципу. Полный список здесь, а мы будем знакомиться с ними по мере необходимости.
Для изменения состояния, используется метод setState, который принимает объект с аргументами, которые нужно изменить. Например, у нас есть состояние:
...
getInitialState: function() {
return {
visible: false,
rating: 0,
eshe_odno_svoistvo: 'qweqwe'
};
}
...
Чтобы изменить рейтинг, нужно написать следующий setState:
this.setState({rating: 100500})
Чтобы изменить все три свойства:
this.setState({
rating: 100500,
visible: true,
eshe_odno_svoistvo: 'привет'
})
Так же у setState есть возможность указать callback функцию, которая будет вызвана после того, как новое состояние "установится".
...
readmoreClick: function(e) {
e.preventDefault();
this.setState({visible: true}, function() {
alert('Состояние изменилось');
});
},
...
Напоследок, немного о стиле кода.
У ссылки "подробнее" получилась длинная строка, кому-то может понравится такой вариант:
...
return (
<div className='article'>
<p className='news__author'>{author}:</p>
<p className='news__text'>{text}</p>
<a href="#"
onClick={this.readmoreClick}
className={'news__readmore ' + (visible ? 'none': '')}>
Подробнее
</a>
<p className={'news__big-text ' + (visible ? '': 'none')}>{bigText}</p>
</div>
)
...
Я не люблю длинные строки, поэтому оставлю второй вариант.
Исходный код на данный момент.
Last updated
Was this helpful?