So we know to pass information from a parent down to a child we use props. Well, as it turns out, to do the opposite: it is NOT that simple.
So how can we send information from a child component to its parent component? You would only need to pass information from a child to a parent component when something happening in the child component directly affects the parent. Take a delete button for example. A delete button that removes something from the application.
The way we would handle this is by creating a callback function in the parent component and passing it down to the child as a prop.
In my application, I needed to make a delete button functional, but the delete button lives in a nested child component.
So I have app
function app () {
const [projects, setProjects] = useState([]);
return (
<ProjectList projects={projects} />
)
}
And ProjectList which returns all the projects I want to display in my application (with props passed down by app).
function ProjectList ({ projects}) {
return projects.map(project => {
return (
<ProjectItem
key={project.id}
project={project}
/>
)
})
};
return (
<section>
<table>
<tr>
<td><h3>Title</h3></td>
<td><h3>Description</h3></td>
</tr>
{renderProjects(projects)}
</table>
</section>
)
}
I created a table to better fit my layout, but as you can see, I created a seperate component to take care of each individual Project in my list of projects. That component looks like this:
function ProjectItem({ project }) {
const { id, title, description } = project
return(
<tr>
<td>{title}</td>
<td>{description}</td>
<td className="delete-button">
<button className="delete-button"> x </button>
</td>
</tr>
)
}
So in order to make my delete button functional, I need to get the click to reach all the way to the app component since Projects state lives in app. The app component displays ProjectList and ProjectList needs ProjectListItem in order to display each project. So let's create the call back function.
function app () {
const [projects, setProjects] = useState([]);
function onProjectDelete (projectId) {
setProjects(projects => projects.filter(Project => Project.id !== projectId))
};
return (
<ProjectList projects={projects} onProjectDelete={onProjectDelete} />
)
}
Then accept it in our ProjectList component and pass it down to our ProjectItem component.
function ProjectList ({ projects, onProjectDelete }) {
return projects.map(project => {
return (
<ProjectItem
key={project.id}
project={project}
onProjectDelete={onProjectDelete}
/>
)
})
};
.......
Now we accept it in our ProjectItem component. We now must create a function that will take in onProjectDelete and be handled by the onClick event.
function ProjectItem({ project, onProjectDelete }) {
const { id, title, description } = project
function handleDelete () {
onProjectDelete(id);
}
return(
<tr>
<td>{title}</td>
<td>{description}</td>
<td className="delete-button">
<button className="delete-button" onClick={handleDelete}> x </button>
</td>
</tr>
)
}
And there we have sucessfully created a way to connect the information happening in ProjectItem all the way back up to state in the App component.
Top comments (0)