> For the complete documentation index, see [llms.txt](https://max-frontend.gitbook.io/react-course-ru/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/ispolzovanie_state.md).

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

*ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в* [*telegram канале*](http://bit.ly/2tS7QUC) *или* [*twitter*](http://bit.ly/2HADDLE)

*На* [*канале*](http://bit.ly/2tS7QUC) *так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы,* [*присоединяйтесь*](http://bit.ly/2tS7QUC)*!*

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

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

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

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

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

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

```javascript
var my_news = [
  {
    author: 'Саша Печкин',
    text: 'В четчерг, четвертого числа...',
    bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'
  },
  {
    author: 'Просто Вася',
    text: 'Считаю, что $ должен стоить 35 рублей!',
    bigText: 'А евро 42!'
  },
  {
    author: 'Гость',
    text: 'Бесплатно. Скачать. Лучший сайт - http://localhost:3000',
    bigText: 'На самом деле платно, просто нужно прочитать очень длинное лицензионное соглашение'
  }
];
```

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

```javascript
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>
    )
  }
});
```

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

Проверим...

![big text screenshot](/files/-LvLnP5-P0wpfSkHIaYE)

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

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

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

### getInitialState

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

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

![big text state screen](/files/-LvLnP521PBEZbUuTimP)

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

```javascript
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**, а не просто перезаписывать значение переменной.

```javascript
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* + функция-обработчик. Существуют и другие стандартные события, которые работают по такому же принципу. Полный список [здесь](https://facebook.github.io/react/docs/events.html), а мы будем знакомиться с ними по мере необходимости.

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

```javascript
...
getInitialState: function() {
    return {
      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}, function() {
      alert('Состояние изменилось');
    });
  },
...
```

Напоследок, немного о стиле кода.

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

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

Я не люблю длинные строки, поэтому оставлю второй вариант.

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