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

В течении всего учебника я учил вас думать о данных, а потом в 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

Итого:

Исходный код

Last updated