# Порефакторим...

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

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

## Порефакторим...

Для начала, удалите вовсе компонент `<Comments />` (и `var Comments =...` соответственно).

Далее, давайте представим: у наших новостей появляются какие-то дополнительные поля, пользователь начинает взаимодействовать с ними, например "пометить как прочитанное" и так далее. Нам было бы удобно, чтобы каждая новость была представлена компонентом.

**Задача**: `<News />` должен рендерить список компонентов `<Article />`. Каждый компонент `<Article />` должен получать соответствующие данные, например: первый экземпляр получит первый элемент массива, второй - второй и так далее.

То есть, раньше в map мы возвращали JSX-разметку. Но мы так же можем возвращать и компонент.

Попробуйте сами, а потом смотрите решение ниже.

Подсказка **#1**: if-else нашего компонента `<News />`

```javascript
if (data.length > 0) {
  newsTemplate = data.map(function(item, index) {
    return (
      <div key={index}>
        <Article data={item} />
      </div>
    )
  })
} else {
  newsTemplate = <p>К сожалению новостей нет</p>
}
```

Подсказка **#2** (по сути решение задачи): компонент `<Article />`

```javascript
var Article = React.createClass({
  render: function() {
    var author = this.props.data.author,
        text = this.props.data.text;

    return (
      <div className="article">
        <p className="news__author">{author}:</p>
        <p className="news__text">{text}</p>
      </div>
    )
  }
});
```

Что любопытно, больше не изменилось ни-че-го.

Замените фразу "всем привет, я компонент App..." на обычный `<h3>` заголовок - "Новости".

```javascript
var App = React.createClass({
  render: function() {
    return (
      <div className="app">
        <h3>Новости</h3>
        <News data={my_news} />
      </div>
    );
  }
});
```

Добавьте красоты (CSS) по вкусу, либо возьмите мой вариант:

_css/app.css_

```css
.none {
  display: none !important;
}

body {
  background: rgba(0, 102, 255, 0.38);
  font-family: sans-serif;
}

p {
  margin: 0 0 5px;
}

.article {
  background: #FFF;
  border: 1px solid rgba(0, 89, 181, 0.82);
  width: 600px;
  margin: 0 0 5px;
  box-shadow: 2px 2px 5px -1px rgb(0, 81, 202);
  padding: 3px 5px;
}

.news__author {
  text-decoration: underline;
  color: #007DDC;
}
.news__count {
  margin: 10px 0 0 0;
  display: block;
}
```

С новыми стилями, код сценария выглядит так:

_js/app.js_

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

var Article = React.createClass({
  render: function() {
    var author = this.props.data.author,
        text = this.props.data.text;

    return (
      <div className='article'>
        <p className='news__author'>{author}:</p>
        <p className='news__text'>{text}</p>
      </div>
    )
  }
});

var News = React.createClass({
  render: function() {
    var data = this.props.data;
    var newsTemplate;

    if (data.length > 0) {
      newsTemplate = data.map(function(item, index) {
        return (
          <div key={index}>
            <Article data={item} />
          </div>
        )
      })
    } else {
      newsTemplate = <p>К сожалению новостей нет</p>
    }

    return (
      <div className='news'>
        {newsTemplate}
        <strong className={'news__count ' + (data.length > 0 ? '':'none') }>Всего новостей: {data.length}</strong>
      </div>
    );
  }
});

var App = React.createClass({
  render: function() {
    return (
      <div className='app'>
        <h3>Новости</h3>
        <News data={my_news} />
      </div>
    );
  }
});

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
```

Обратите внимание, я добавил несколько классов, один из них я добавил к тэгу **strong**. Как вы помните, у нас там было условие:

```javascript
<strong className={data.length > 0 ? '':'none'}>Всего новостей: {data.length}</strong>
```

Так как атрибут _class_ (либо в JSX - _classname_) у элемента принимает строку, то можно представить элемент с несколькими классами:

```javascript
<div className={ 'class1' + 'class2' + 'class3' }>text</div>
```

В таком случае к нашему элементу применится ... класс **"class1class2class3"**, что естественно, так как мы забыли пробелы. Наверное, мы хотели сделать так:

```javascript
<div className={ 'class1 ' + 'class2 ' + 'class3' }>text</div>
```

Теперь у нас будет элемент с классами: class1, class2, class3

Именно поэтому, мы и получили следующее выражение:

```javascript
<strong className={'news__count ' + (data.length > 0 ? '':'none') }>Всего новостей: {data.length}</strong>
```

Посмотрим, что вышло в итоге:

![порефакторим screenshot](https://2032922960-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8nmqH3uUpCfPAD%2F-LvLmydxF5hwFbPJLrLG%2F-LvLn8pE-a2EDerQnoUX%2Fscreen_refactorim.jpg?generation=1575561847942810\&alt=media) Либо:

![no news рефакторим](https://2032922960-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8nmqH3uUpCfPAD%2F-LvLmydxF5hwFbPJLrLG%2F-LvLn8pG1Wfuwz5DiUxQ%2Fscreen_refactorim_no_news.jpg?generation=1575561847951012\&alt=media)

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