How would I know when to update the parent's state through a child?


#1

Question

How would I know when to update the parent’s state through a child?

Answer

You will know by the design of the application, although it is very common to have a parent’s state altered by a child because of the nature of React and its modularity through the components, for example, if we have a page with a navigation bar, a preview section with an image and text, and a form where you can upload an image and write the text, then our application might look like this as a diagram:

App (Main parent)

  • NavBar component (child of App, parent of each SelectionLink)
  •    -
    
  •    -  SelectionLink Component (child of NavBar)
    
  • Preview component (child of App)
  • Form component (child of App)

Since we know that the children cannot directly communicate with each other we need to use the state in the App component to create that interaction. that way, when we chose a picture it will be displayed, and when we write in the input tag from the Form component it will show on our preview component. the passing of props from App would look like so:

...
class App extends Component {
  constructor(){
    this.state = {
      img : '../../public/img/temporaryImg.jpg',
      text: 'Add some text!'
    }
    this.onChange = this.onChange.bind(this);
    this.onUpload = this.onUpload.bind(this);
  }

  onChange(txt){
    this.setState({ 
      text: txt
    })
  }

  onUpload(img){
    this.setState({
      img: img
    })
  }

  render(){
    return(
      <div>
        <Nav/>
        <Preview text = { this.state.text } img = { this.state.img }/>
        <Form changeText = { this.onChange } imageUpdate = { this.onUpload } />
      </div>
    )
}

...

There as we can see we have our state in App, as our main parent, and we use that to our advantage by sharing that state with Preview for it to be displayed, and then we share the methods that manipulate App's state with Form to update the state and therefore what is display on Preview at each interaction with Form.

We will want to be careful though, this way of manipulating interaction works well, but we don’t want to have all our state in one place and we don’t want to have a state heavy parent component. There is one big reason for it: every minor change will trigger a re-render in all components that are children of that parent, for example, if we where to add more functionalities to our previous application, and we ended up with twelve properties in our App's state which is being distributed between five components, and we just decide to edit the text in our form, all our five children components will rerender along with App, because App's state has changed and it needs to reflect the changes. In cases like this, we need to be smart about where we need certain data and how it will be best to store it in state, either in a closer parent component or the component that will create the change, this will create less stress on the app by just re-rendering the necessary components, going back to our previous example having a Container component that will be parent of Preview and Form, as well as carrying the state, will allow us to keep the same functionality, but at every state change, it will be only Container and its children what will re-render, and not have to be also App and Nav which will have to reason for it.

App (Main parent)

  • NavBar component (child of App, parent of each SelectionLink)
  •    -
    
  •    -  SelectionLink Component (child of NavBar)
    
  • Container component (child of App, parent of Preview and Form)
  •    -
    
  •    - Preview component (child of Container)
    
  •    -  Form component (child of Container)