# Использование 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) на данный момент.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://max-frontend.gitbook.io/react-course-ru/ispolzovanie_state.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
