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 an- onSavefunction that requires a- projectas a parameter and returns- void.- 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 - onSave- propand pass a new- Projectthat you create inline for now with just a name as shown below.- Update the - <form>tag in the- rendermethod 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 an- onSaveevent handler that requies a- projectas a parameter and returns- void.- src\projects\ProjectList.tsxinterface ProjectListProps {projects: Project[];+ onSave: (project: Project) => void;}
- Update the - <ProjectForm>component tag to handle a- onSaveevent and have it invoke the function passed into the- onSave- prop.- 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.
 