Книга: react-course-ru-v2
Назад: Спам-фильтр
Дальше: getDerivedStateFromProps

componentWillReceiveProps

ComponentWillReceiveProps (CWRP)

Давайте начнем со старого метода жизненного цикла (), который будет поддерживаться до React 17й версии. Нам нужно это знать, потому что много (очень много) кода уже написано и вам, наверняка, достанется такой проект.

src/components/News.js

class News extends React.Component {   componentWillReceiveProps(nextProps) {     console.log({ nextProps })     console.log({ oldProps: this.props })   }   ... }  ...  export { News } 

fresh news

Давайте, мы отвлечемся на секунду и исправим старую ошибку - в компоненте <Add /> у кнопки, сделайте текст "Добавить новость", вместо "Показать Alert".

Продолжим: CWRP в первом аргументе принимает "будущие props", значит мы можем по ним пробежаться, найти новость с "pubg" фрагментом, если она есть и пометить ее как "СПАМ".

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

  • как сделать state на основе props?
  • как изменить состояние, на основе вновь пришедших props?

src/components/News.js

... class News extends React.Component {    state = { // создали состояние     filteredNews: this.props.data,   }    componentWillReceiveProps(nextProps) {     console.log({ nextProps })     console.log({ oldProps: this.props })   }   renderNews = () => {     const { filteredNews } = this.state // используем состояние     let newsTemplate = null      if (filteredNews.length) { // везде data заменена на filteredNews       newsTemplate = filteredNews.map(function(item) {         return <Article key={item.id} data={item} />       })     } else {       newsTemplate = <p>К сожалению новостей нет</p>     }      return newsTemplate   }   render() {     const { filteredNews } = this.state // аналогично, используем состояние      return (       <div className="news">         {this.renderNews()}         {filteredNews.length ? (           <strong className={'news__count'}>             Всего новостей: {filteredNews.length}           </strong>         ) : null}       </div>     )   } } ... 

Изменений немного, просто внимательно пробегитесь по файлу - теперь данные берем из filteredNews, но при этом они нам изначально приходят в props (поэтому propTypes оставили без изменений).

Внутри CWRP можно безопасно использовать setState, так как это не приведет к дополнительной (лишней) перерисовке.

src/components/News.js

componentWillReceiveProps(nextProps) {   let nextFilteredNews = [...nextProps.data]    nextFilteredNews.forEach((item, index) => {     if (item.bigText.toLowerCase().indexOf('pubg') !== -1) {       item.bigText = 'СПАМ'     }   })    this.setState({ filteredNews: nextFilteredNews }) } 

В данном фрагменте ничего необычного, для тех кто в теме основ (я понимаю, что фраза "знать основы" набила оскомину, но их действительно нужно знать).

В nextFilteredNews склонировали весь массив новостей из "будущих" пропс, затем пробежались по нему, в if выяснили, есть ли pubg в введеном в bigText тексте, и если есть, заменили на "СПАМ".

Для тех, у кого есть пробелы:

  • (MDN)
  • (MDN)

Итого:

  • научились создавать state на основе props;
  • научились обновлять state на основе новых props без лишней перерисовки;

Назад: Спам-фильтр
Дальше: getDerivedStateFromProps