Updating rendered elements

Updating rendered elements

So far, this course has only asked you to take a static set of data, and render it to the DOM once. But what happens when the data changes?

Despite what you may expect from a tool called React, nothing changes. You can see this in the example below; even though 'Carol' is added to the data array, she doesn’t appear in the rendered list.

index.js
import React from 'react'
import ReactDOM from 'react-dom'

function List(props) {
  return (
    <ul>
      {props.data.map(item =>
        <li key={item}>{item}</li>
      )}
    </ul>
  )
}

let data = [
  'Alice',
  'Bob',
]

// The render uses the initial value of `data`
ReactDOM.render(
  <List data={data} />,
  document.getElementById('root')
)

// Mutating the `data` array doesn't cause a re-render!
data.push('Carol')
Build In Progress

When data changes in a React app, you’ll need to manually order a re-render. But how?

In fact, there are two ways of doing it. And you’ve already seen one of them, so we’ll cover that first: you can just call ReactDOM.render() again.

#What does render do?

The ReactDOM.render() function renders a React element to a DOM node. But what is meant by “render”? This is an interesting question, because the answer depends on the situation:

  • On the first call to ReactDOM.render(reactElement, domNode), the DOM Node’s content will be replaced with the content specified by the React Element.

  • But if the DOM Node already contains content rendered by React, this content will be updated to reflect the new React Element.

For a concrete example, consider the contact list from earlier. If the data array changes, perhaps because the user has added a new contact, then you can call ReactDOM.render with a new ContactList element to render an update.

Try it out in the example below. When you click the Add button, the update() function will be called, which adds a new friend to your contact list and then re-renders the app.

index.js
Contacts.js
billionaires.js
styles.css
import React from 'react'
import ReactDOM from 'react-dom'
import { billionaires } from './billionaires.js'
import { ContactList, Contact } from './Contacts.js'

const domNode = document.getElementById('root')

// The App's top-level component, which is rendered both initially
// and after an update.
function App(props) {
  return (
    <ContactList>
      {props.contacts.map((contact, i) =>
        <Contact {...contact} key={i} />
      )}
      <button onClick={update}>
        Add
      </button>
    </ContactList>
  )
}

// Called whenever you click "Add"
function update() {
  let updatedContacts = billionaires.concat({
    name: 'Masayoshi Son',
    email: 'mson@softbank.co.jp',
  })
  
  ReactDOM.render(
    <App contacts={updatedContacts} />,
    domNode
  )
}

// The initial render
ReactDOM.render(
  <App contacts={billionaires} />,
  domNode
)
Build In Progress

You may have noticed that the above code uses an onClick prop to handle events. We’ll go into more detail on this in the next section.

Let me also point out the top level App component. Many React apps follow the convention of naming their top-level element App. In fact, the popular create-react-app tool also uses this name in its generated code. But know that you’re free to name your components whatever you’d like.

But before learning about event handling or structuring an app, we still need to figure out exactly ReactDOM.render() does!

Progress to next section.