Як примусово оновити дочірній компонент React: простий спосіб

Примітка: Станом на React 16 componentWillReceiveProps()застаріло, тобто якщо ви використовуєте цю версію або новішу у своєму проекті, це не є гарною порадою для вас.

У світі реагування примусове рендеринг відмовляється. Ви повинні дозволити DOM подбати про себе, коли React сприймає зміни stateабо props. Щоб слідувати цим шаблонам, нам іноді доводиться робити речі, які здаються трохи безглуздими. Розглянемо такий сценарій:

У нас є два компоненти - батько та дитина. Батько робить виклик API для отримання user. З цього ми отримуємо такі речі , як name, age, favorite color. Ми також отримуємо idз нашої бази даних. Ми передамо це нашому дочірньому компоненту, який також збирається здійснити виклик API, з ідентифікатором користувача. Чудово - у наш додаток надходить багато даних.

Скажімо, ми зберігаємо список взуття в базі даних. Коли користувач змінює свої кольорові переваги, сервер записує нові дані до списку взуття користувача. Чудово! Крім того, ми не бачимо нового списку взуття в нашому дочірньому компоненті. Що дає?

Примітка : Звичайно, нам слід просто взяти черевики із дзвінка для користувача - це лише спрощене пояснення.

Реагуйте на основи рендерингу

Короткий момент полягає в тому, що React буде оновлювати лише ті частини DOM, які змінилися. У цьому випадку propsми передаємо компонент взуття ( userId) не змінився, тому в нашому дочірньому компоненті нічого не змінюється.

Налаштування кольору для користувача оновлюється, коли ми отримуємо нову інформацію з API - припускаючи, що ми щось робимо із відповіддю після оновлення користувача.

Але оскільки React не бачить причин для оновлення списку взуття, цього не стане - хоча на нашому сервері взуття зараз інша.

Початковий код

const UserShow extends Component { state = { user: {} } componentDidMount() { this.fetchUser().then(this.refreshUser) } setNewColor = color => { this.updateUser({color}).then(this.refreshUser) } refreshUser = res => this.setState({user: res.data.user}) render() { const { user } = this.state; return ( User name: {user.name} Pick color: {colors.map(color => this.setNewColor(color)} />)} )} ) } }

Нашим ShoeListпросто буде список взуття, який ми отримаємо з сервера із ідентифікатором користувача:

const ShoeList extends Component { state = { shoes: [] } componentDidMount() { this.fetchShoes(this.props.id) .then(this.refreshShoeList) } refreshShoeList = res => this.setState({ shoes: res.data.shoes }) render() { // some list of shoes } }

Якщо ми хочемо, щоб компонент взуття захопив новий список взуття, нам потрібно оновити реквізит, який ми йому надсилаємо. В іншому випадку оновлення не побачить потреби.

Насправді, як це написано, це ShoeListніколи не оновлюється, оскільки ми не залежамо від реквізиту для візуалізації. Давайте це виправимо.

Запуск дочірнього компонента для повторного відтворення

Щоб змусити дочірній компонент повторно відтворити - і здійснити новий виклик API - нам потрібно буде передати опис, який зміниться, якщо налаштування кольору користувача змінилися.

Для цього ми додамо метод до setNewColor:

[...] setNewColor = color => { this.updateUser({color}).then(res => { this.refreshUser(res); this.refreshShoeList(); }) } refreshShoeList = () => this.setState({refreshShoeList: !this.state.refreshShoeList}) [...] 

This is a simple switch we can flip. I’ve kept things as simple as possible, but in production we’d want to make sure that the color we’re setting is different than the color we had before. Otherwise, there will be nothing to update.

Now in the ShoeList:

componentWillReceiveProps(props) { const { refresh, id } = this.props; if (props.refresh !== refresh) { this.fetchShoes(id) .then(this.refreshShoeList) } }

If you pass only refreshShoeList and then toggle based on that boolean, the component will just update forever and ever and ever.

We need to make sure the switch has flipped only once — so we’ll just check that the props coming in are different than the props we had before. If they are different, we’ll make a new API call to get the new list of shoes.

And boom — our child component has been “forced” to update.

componentWillReceiveProps

It’s worth taking just one more minute to review what’s going on in that last piece of code. In componentWillReceiveProps we have our only opportunity to view new props as they are coming in and compare them with previous props.

Here we can detect changes (like in refresh) and we can also make checks for new props (note, for instance, that refresh is initially undefined).

This React method is a very powerful way to manipulate and examine props.

Original text