> For the complete documentation index, see [llms.txt](https://max-frontend.gitbook.io/react-course-ru-v2/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://max-frontend.gitbook.io/react-course-ru-v2/ispolzovanie-state.md).

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

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

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

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

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

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

```javascript
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! Вся инфа на сайте, не реклама!'
  }
];
```

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

```javascript
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](/files/-LvLnSprHuVObJEeaLNE)

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

```javascript
...
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:

```javascript
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](/files/-LvLnSptR_NSZO-a2EDL)

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

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

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

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

```javascript
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 выражение. Если вы не знакомы с И / ИЛИ, то рекомендую почитать у Кантора ([Логические операторы](https://learn.javascript.ru/logical-ops)).

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

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

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

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

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

```javascript
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](/files/-LvLnSpvKN2FjxaDmPg0)

**Итого**:

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

Для обработки клика, используется свойство *onClick* + функция-обработчик. Существуют и другие стандартные события, которые работают по такому же принципу. Полный список [здесь](https://reactjs.org/docs/events.html#supported-events). Мы будем знакомиться с ними по мере необходимости.

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

```javascript
...
state = {
  visible: false,
  rating: 0,
  eshe_odno_svoistvo: 'qweqwe'
}
...
```

Чтобы изменить рейтинг, нужно написать следующий setState:

```javascript
this.setState({rating: 100500})
```

Чтобы изменить все три свойства:

```javascript
this.setState({
    rating: 100500,
    visible: true,
    eshe_odno_svoistvo: 'привет'
})
```

Так же у *setState* есть возможность указать *callback* функцию, которая будет вызвана после того, как новое состояние "установится".

```javascript
...
readmoreClick: function(e) {
    e.preventDefault();
    this.setState({ visible: true }, () => {
      alert('Состояние изменилось');
    });
  },
...
```

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

Посмотреть полный список возможностей setState можно в [документации](https://reactjs.org/docs/react-component.html#setstate).

[Исходный код](https://github.com/maxfarseer/react-course-ru-v2/tree/chp7-use-state) на данный момент.
