Книга: react-course-ru-v2
Назад: getDerivedStateFromProps
Дальше: Заключение

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

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

В течении всего учебника я учил вас думать о данных, а потом в CWP и gDSFR взял и сделал из образно stateless (хоть он и был через class - состояния у него не было) компонента - statefull. Это было сделано для удобства объяснений.

Смотрите, если мы откатим наш <News /> на два урока назад (когда компонент просто получал props), то мы сможем в <App /> использовать gDSFR и там "рубить спам". Таким образом, мы бы опять решили задачу без изменения stateless компонента.

Было: компонент <News /> умел отображать данные. Стало: компонент <News /> умеет отображать данные и помечать спам.

Задача: обрабатывать данные в <App />, вернуть <News /> к прежнему "тупому" образу жизни.

Подсказка: вы запросто можете сделать все что нужно в <App />, так как мы только что отработали этот прием.

Подсказка: в <App /> новости лежат в state, а не в props.

Напоминаю, как выглядел <News />:

src/components/News.js

import React from 'react' import PropTypes from 'prop-types' import { Article } from './Article'  class News extends React.Component {   renderNews = () => {     const { data } = this.props     let newsTemplate = null      if (data.length) {       newsTemplate = data.map(function(item) {         return <Article key={item.id} data={item} />       })     } else {       newsTemplate = <p>К сожалению новостей нет</p>     }      return newsTemplate   }   render() {     const { data } = this.props      return (       <div className="news">         {this.renderNews()}         {data.length ? (           <strong className={'news__count'}>             Всего новостей: {data.length}           </strong>         ) : null}       </div>     )   } }  News.propTypes = {   data: PropTypes.array.isRequired, }  export { News } 

Решение

Полный код компонента <App />

src/App.js

import React from 'react' import { Add } from './components/Add' import { News } from './components/News' import './App.css'  class App extends React.Component {   state = {     news: null,     isLoading: false,   }   static getDerivedStateFromProps(props, state) {     let nextFilteredNews      // смотрим в state.news (ранее смотрели в props)     // и проверяем, чтобы не клоинировать null     // например, в момент первой отрисовки     if (Array.isArray(state.news)) {       nextFilteredNews = [...state.news]        nextFilteredNews.forEach((item, index) => {         if (item.bigText.toLowerCase().indexOf('pubg') !== -1) {           item.bigText = 'СПАМ'         }       })        return {         filteredNews: nextFilteredNews,       }     }      return null   }   componentDidMount() {     this.setState({ isLoading: true })     fetch('http://localhost:3000/data/newsData.json')       .then(response => {         return response.json()       })       .then(data => {         setTimeout(() => {           this.setState({ isLoading: false, news: data })         }, 1000) // изменил таймер на 1000, чтобы не ждать долго       })   }   handleAddNews = data => {     const nextNews = [data, ...this.state.news]     this.setState({ news: nextNews })   }   render() {     const { news, isLoading } = this.state      return (       <React.Fragment>         <Add onAddNews={this.handleAddNews} />         <h3>Новости</h3>         {isLoading && <p>Загружаю...</p>}         {Array.isArray(news) && <News data={news} />}       </React.Fragment>     )   } }  export default App 

Итого:

Назад: getDerivedStateFromProps
Дальше: Заключение