Lab 14: Component Communication through Multiple Levels
Objectives
- In a child component, accept a function as a prop and invoke it and pass a parameter
- At the next level in the component hierarchy, accept a function as a prop and invoke it
- In a parent component, implement a function and pass it as a prop to a child component
Steps
In a child component, accept a function as a prop and invoke it and pass a parameter
Open the file
src\projects\ProjectForm.tsx.On the
ProjectFormPropsinterface, add anonSavefunction that requires aprojectas a parameter and returnsvoid.src\projects\ProjectForm.tsx...+ import { Project } from './Project';interface ProjectFormProps {+ onSave: (project: Project) => void;onCancel: () => void;}...Create an event handler function
handleSubmitto handle the submission of the form.The function should prevent the default behavior of the browser to post to the server and then invoke the function passed into the
onSavepropand pass a newProjectthat you create inline for now with just a name as shown below.Update the
<form>tag in therendermethod to invoke handleSubmit and pass the SyntheticEvent object representing the DOM submit event.src\projects\ProjectForm.tsx+ import React, { SyntheticEvent } from 'react';...- function ProjectForm({ onCancel }: ProjectFormProps) {+ function ProjectForm({ onSave, onCancel }: ProjectFormProps) {+ const handleSubmit = (event: SyntheticEvent) => {+ event.preventDefault();+ onSave(new Project({ name: 'Updated Project' }));+ };return (<form className="input-group vertical"+ onSubmit={handleSubmit}><label htmlFor="name">Project Name</label><input type="text" name="name" placeholder="enter name" /><label htmlFor="description">Project Description</label><textarea name="description" placeholder="enter description" /><label htmlFor="budget">Project Budget</label><input type="number" name="budget" placeholder="enter budget" /><label htmlFor="isActive">Active?</label><input type="checkbox" name="isActive" /><div className="input-group"><button className="primary bordered medium">Save</button><span /><button type="button" className="bordered medium" onClick={onCancel}>cancel</button></div></form>);}export default ProjectForm;
At the next level in the component hierarchy, accept a function as a prop and invoke it
Open the file
src\projects\ProjectList.tsx.On the
ProjectListPropsinterface, add anonSaveevent handler that requies aprojectas a parameter and returnsvoid.src\projects\ProjectList.tsxinterface ProjectListProps {projects: Project[];+ onSave: (project: Project) => void;}Update the
<ProjectForm>component tag to handle aonSaveevent and have it invoke the function passed into theonSaveprop.src\projects\ProjectList.tsxinterface ProjectListProps {projects: Project[];onSave: (project: Project) => void;}- function ProjectList({ projects }: ProjectListProps) {+ function ProjectList({ projects, onSave }: ProjectListProps) {const [projectBeingEdited, setProjectBeingEdited] = useState({});const handleEdit = (project: Project) => {setProjectBeingEdited(project);};const cancelEditing = () => {setProjectBeingEdited({});};return (<div className="row">{projects.map((project) => (<div key={project.id} className="cols-sm">{project === projectBeingEdited ? (<ProjectForm+ onSave={onSave}onCancel={cancelEditing} />) : (<ProjectCard project={project} onEdit={handleEdit} />)}</div>))}</div>);}export default ProjectList;
In a parent component, implement a function and pass it as a prop to a child component
In the file
src\projects\ProjectsPage.tsx:- Add a
saveProjectevent handler that takes aprojecttoProjectPageandconsole.log's the project out. - Wire up the onSave event of the
<ProjectList />component rendered in theProjectPageto thesaveProjectevent handler.
src\projects\ProjectsPage.tsximport React, { Fragment } from 'react';import { MOCK_PROJECTS } from './MockProjects';import ProjectList from './ProjectList';+ import { Project } from './Project';function ProjectsPage() {+ const saveProject = (project: Project) => {+ console.log('Saving project: ', project);+ };return (<Fragment><h1>Projects</h1><ProjectList+ onSave={saveProject}projects={MOCK_PROJECTS} /></Fragment>);}export default ProjectsPage;- Add a
Verify the application is working by following these steps:
- Open the application in your browser and refresh the page.
- Open the Chrome DevTools to the
console(F12orfn+F12on laptop). - Click the edit button for a project.
- Click the save button on the form.
- Verify the updated project is logged to the Chrome DevTools
console.Note that the
ProjectCardinfo will not be updated at this point.
