Як оновити властивості компонента в ReactJS - о так, це можливо

Якщо ви прочитали офіційні документи React (і вам слід, оскільки це чудовий ресурс React), ви помітите такі рядки:

Незалежно від того, декларуєте ви компонент як функцію чи клас, він ніколи не повинен змінювати власні властивості.

React досить гнучкий, але він має єдине суворе правило:

Всі компоненти React повинні діяти як чисті функції щодо своїх реквізитів.

Реквізит ніколи не оновлюється. Ми повинні використовувати їх як є. Звучить жорстко, правда? Але React має свої причини за цим правилом, і я досить переконаний в їх аргументації. Єдине застереження полягає в тому, що існують ситуації, коли нам може знадобитися ініціювати оновлення реквізиту. І ми скоро дізнаємось як.

Розглянемо такий рядок коду з батьківського компонента:


This is a simple line which every React dev is probably familiar with. You are calling child component. While you are doing that, you are also passing the state of the parent (parentName) to the child. In the child component, this state will be accessed as this.props.childName. Fair enough.

Now if there is any change of name required, parentName will be changed in the parent and that change will automatically be communicated to the child as is the case with the React mechanism. This setup works in most of the scenarios.

But what if you need to update the prop of the child component, and the knowledge of the change required and the trigger to change it is only known to the child? Considering the ways of React, data can only flow from top-to-bottom i.e., from parent-to-child. So then how are we to communicate to the parent that a change to prop is required?

Well, although this is anti-pattern and not recommended, the devs who wrote the language have us covered. Surprise!

We can do it with Callbacks. I know, no surprise there! They seem to come in handy for every problem we face here. Okay, okay, now how?

Original text

Imagine if the above call to the child was modified this way:


Now in addition to a prop childName our needy-child also has an event called onNameChange exposed. This is the way to resolve the issue. Our child has done its part. Now it’s the parent’s turn to do what is required. And it need not fret. All it needs to do is define a function onChange as

function onChange(newName) { this.setState({ parentName: newName });}

That’s it. Now whenever and wherever in the child component we wish to update the parentName prop, all we have to do is call `this.props.onNameChange(' My New name') and voilà! You’ll have what you desire. That’s it. Done and dusted.

Hope that was easy to grasp. Let me know in the comments about any difficulties or different ways in which it could have been made easier. Thanks.

One last thing.

React argues against this and they are pretty right about it. This is anti-pattern. So whenever you run into a situation like this, check to see if you could lift your state up or if there is any way you could break your component down. It might sound a wee bit tedious, but know that that’s the way it is supposed to be in React!

Happy Coding.