componentWillReceiveProps

Давайте начнем со старого метода жизненного цикла (componentWillReceiveProps), который будет поддерживаться до 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 тексте, и если есть, заменили на "СПАМ".

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

Итого:

  • научились создавать state на основе props;

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

Исходный код