We can start by delving into a basic example problem with utilizing components in a single page app that requires updated information from those components. The solution outlined below will show how we pass data to the child, edit it, and finally pass it back to the parent. You can also check out this blog on the basics of React states and props before going further. This example will be a single page that loads data for a specific object in our database. We’ll be working with a JSON object response that is loaded to our local storage, pass that data to all components on the page, then edit and send back the data to the main page and update the state.

Breaking it down, the page will be that of a user’s basic information. It will be symbolizing a user profile page that loads the data to be edited. In this example, a user can save a list of names associated to their account called companions. First and foremost, we load the data into states that we may then utilize within our page and pass into a child component called CompanionList which will parse the data and display the list of names.

The parent component is the EditPage component that is grabbing the data from an example script we’re calling getCurrentUser that loads their current information behind the scenes. Ideally we are using a router that will check if the user is logged in and then route to the parent page when the user requests the page.

// Sample endpoint data loaded when the user logged in; the getCurrentUser() example is loaded from within /src/components/index.js that is also importing other component JS files such as Form and CompanionList
 
{
id: '1a2b3c4d5e',
name: 'The Doctor',
companions: {
0: {
name: 'Rose Tyler',
},
1: {
name: 'Mickey Smith',
},
2: {
name: 'Adelaide Brooke',
},
3: {
name: 'Amy Pond',
},
4: {
name: 'Rory Williams',
}
}
}
// Basic edit profile page with components in /src/pages/editpage.js
 
import React from 'react'
import { getCurrentUser, Form, CompanionList } from '../components'
 
const user = getCurrentUser()
 
class EditPage extends React.Component {
constructor(props) {
super(props)
 
this.state = {
user: user.name,
companions: user.companions
}
}
 
render() {
return (
<Form>
<input type='text' value={this.state.user} />
<CompanionList companions={this.state.companions} />
<input type='submit' value='Save' />
</Form>
)
}
}
 
export default EditPage

By far the easiest task is getting our data from the parent into a child component simply by passing the data into a state that we can manage and add it to a child component’s prop. Once inside the child component, we can parse and edit the data without complicating the edit page that will take the data and save it once the form is submitted. Unforuntately as is, the parent component only has access to the unaltered states.

Below we can see the CompanionList and updated EditPage to show how a child will parse the data and send back the updated data with an onChange prop.

// Child component in /src/components/companionList.js
 
import React from 'react'
 
const CompanionList = ({ companions, onChange }) => {
const list = companions
 
const handleList = () => {
list.map(name => { return <li>{name}</li> })
}
 
function addName(e) {
list.push({ name: e.target.value })
onChange(list)
}
 
return (
<div>
<input type='text' placeholder='Type a new name here...' />
<button onClick={e => addName(e)}>Add</button>
<ul>{handleList()}</ul>
</div>
)
}
// Updated parent component in /src/pages/editpage.js
 
import React from 'react'
import { getCurrentUser, Form, CompanionList } from '../components'
 
const user = getCurrentUser()
 
class EditPage extends React.Component {
constructor(props) {
super(props)
 
this.state = {
user: user.name,
companions: user.companions
}
}
 
updateList(newList) {
this.setState({ companions: newList }, ())
}
 
render() {
return (
<Form>
<input type='text' value={this.state.user} />
<CompanionList companions={this.state.companions} onChange={this.updateList.bind(this)} />
<input type='submit' value='Save' />
</Form>
)
}
}
 
export default EditPage

The CompanionList is taking our companions array and mapping it out as a collection of list items that is rendered in an unordered list. Above that is an add button and text input field to add a new companion name. It adds it to the current list of companions then we call the onChange prop where we've added a function to grab the list from the child component and update the companion state in the parent component. We can even call on a function after setState to validate the fields as an example.

To recap, the parent component is binding a function to an onChange prop of the child component. The child component is taking the companions prop and building a list of names to display. The user may input a new name and once the add button is clicked it updates the list with the new name and passes the updated information back to the parent to update the main companion state.

And there you have it, passing data to and from components on a single page. The sheer power of React for the frontend development experience allows for so much control over dynamic and user-driven data without bogging down the site with heavy scripts. A happy developer creates happy user experiences.