Книга: react-course-ru-v2
Назад: Prop-types
Дальше: Подробнее о state

Использование state

Использование state

Вернемся от теории к практике: давайте покликаем по ссылкам-кнопочкам, поизменяем свойства компонентов...

Упс, не выйдет! Как вы помните, свойства (this.props) следует использовать только для чтения, а для динамических свойств нужно использовать так называемое "состояние" (state).

Итак, встречайте - this.state ;)

Так как мне нужно в этом разделе сохранить минимум теории и больше практики, сразу перейдем к делу. Предлагаю вместе решить следующую задачу: у новости есть ссылка "подробнее", по клику на которую - бинго, текст новости целиком.


Начнем с изменения данных:

const myNews = [   {     id: 1,     author: 'Саша Печкин',     text: 'В четверг, четвертого числа...',     bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'   },   {     id: 2,     author: 'Просто Вася',     text: 'Считаю, что $ должен стоить 35 рублей!',     bigText: 'А евро 42!'   },   {     id: 3,     author: 'Max Frontend',     text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35',     bigText: 'А евро опять выше 70.'   },   {     id: 4,     author: 'Гость',     text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru',     bigText: 'Еще есть группа VK, telegram и канал на youtube! Вся инфа на сайте, не реклама!'   } ]; 

Затем, научимся отображать полный текст новости сразу после вводного текста:

class Article extends React.Component {   render() {     const { author, 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>     )   } }  Article.propTypes = {   data: PropTypes.shape({     author: PropTypes.string.isRequired,     text: PropTypes.string.isRequired,     bigText: PropTypes.string.isRequired // добавили propTypes для bigText   }) } 

Опять же, больше ничего изменять не нужно. Данные корректно отобразятся.

Проверим...

news with readmore

Отлично, можно продолжать работу: добавим ссылку - "подробнее". Приведу фрагмент кода:

... 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> ) ... 

Проверьте и если все ок - мы готовы к работе с состоянием компонента.


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

С состоянием (state) можно работать только в statefull компонентах (class)

Если вы определяете какое-то изменяемое свойство в компоненте, необходимо указать начальное состояние (в терминологии react.js - initial state). Для этого, у компонента нужно просто определить свойство state:

class Article extends React.Component {   state = {     visible: false, // определили начальное состояние   }   render() {     const { author, text, bigText } = this.props.data     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:

news initial state

В состоянии (в state) появилось свойство. Будем использовать его в момент render'а.

Формализуем задачу:

  • если значение this.state.visible === false -> рисуй "подробнее", не рисуй "большой текст";
  • если же this.state.visible === true -> не рисуй "подробнее", рисуй большой текст;

Будем использовать логическое выражение внутри JSX, значит - фигурные скобки, и внутри js-выражение.

class Article extends React.Component {   state = {     visible: false,   }   render() {     const { author, text, bigText } = this.props.data     const { visible } = this.state // вытащили visible из this.state     return (       <div className='article'>         <p className='news__author'>{author}:</p>         <p className='news__text'>{text}</p>         { /* если не visible, то показывай */           !visible && <a href="#" className='news__readmore'>Подробнее</a>         }         { /* если visible, то показывай */           visible && <p className='news__big-text'>{bigText}</p>         }       </div>     )   } } 

Мы использовали одну и ту же переменную состояния в двух местах когда описывали обычное javascript выражение. Если вы не знакомы с И / ИЛИ, то рекомендую почитать у Кантора ().

Обратите внимание, для написания комментариев не понадобились дополнительные фигурные скобки, так как мы уже находились внутри "выражения" внутри JSX.

Можете проверить в браузере, и покликать на чекбокс внутри state зоны. Шаблон уже будет реагировать. А мы продолжим делать все это по-человечески, чтобы можно было кликать на "подробнее".


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

Чтобы обработать клик, нам необходимо указать атрибут onClick у элемента.

В качестве обработчика у нас будет функция, которая изменяет состояние. Для изменения состояния, нужно обязательно использовать метод setState, а не перезаписывать значение переменной в this.state напрямую.

class Article extends React.Component {   state = {     visible: false,   }   handleReadMoreClck = (e) => { // добавили метод     e.preventDefault()     this.setState({ visible: true })   }   render() {     const { author, text, bigText } = this.props.data     const { visible } = this.state     return (       <div className='article'>         <p className='news__author'>{author}:</p>         <p className='news__text'>{text}</p>         { /* добавили onClick */           !visible && <a onClick={this.handleReadMoreClck} href="#" className='news__readmore'>Подробнее</a>         }         {           visible && <p className='news__big-text'>{bigText}</p>         }       </div>     )   } } 

Проверьте в браузере, кликните на ссылку "подробнее".

Каждый компонент <Article /> имеет свое состояние! Поэтому, при клике на подробнее в одном из компонентов, только его состояние изменяется, и только у этой новости отображается полный текст.

news last readmore


Итого:

Для сохранения динамических свойств, используется состояние (state) компонента.

Для обработки клика, используется свойство onClick + функция-обработчик. Существуют и другие стандартные события, которые работают по такому же принципу. Полный список . Мы будем знакомиться с ними по мере необходимости.

Для изменения состояния, используется метод setState, который принимает объект с аргументами, которые нужно изменить. Например, у нас есть состояние:

... state = {   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 }, () => {       alert('Состояние изменилось');     });   }, ... 

Еще setState есть возможность... (на самом деле есть, но с нас пока хватит).

Посмотреть полный список возможностей setState можно в .

на данный момент.

Назад: Prop-types
Дальше: Подробнее о state