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.jsx.
- To the - propTypes, add an- onSavefunction.- src\projects\ProjectForm.jsx- ...
 ProjectForm.propTypes = {
 + onSave: PropTypes.func.isRequired,
 onCancel: PropTypes.func.isRequired
 };
 ...
- 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.jsx- ...
 + import { Project } from './Project';
 - function ProjectForm({ onCancel }) {
 + function ProjectForm({ onSave, onCancel }) {
 + const handleSubmit = (event) => {
 + 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.jsx.
- To the - propTypes, add an- onSaveevent handler.- src\projects\ProjectList.jsx- ...
 ProjectList.propTypes = {
 projects: PropTypes.arrayOf(PropTypes.instanceOf(Project)).isRequired,
 + onSave: PropTypes.func.isRequired
 };
 ...
- Update the - <ProjectForm>component tag to handle a- onSaveevent and have it invoke the function passed into the- onSave- prop.- src\projects\ProjectList.jsx- - function ProjectList({ projects }) {
 + function ProjectList({ projects, onSave }) {
 const [projectBeingEdited, setProjectBeingEdited] = useState({});
 const handleEdit = (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.jsx:- 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.jsx- import { MOCK_PROJECTS } from './MockProjects';
 import ProjectList from './ProjectList';
 function ProjectsPage() {
 + const saveProject = (project) => {
 + console.log('Saving project: ', project);
 + };
 return (
 <>
 <h1>Projects</h1>
 <ProjectList
 + onSave={saveProject}
 projects={MOCK_PROJECTS} />
 </>
 );
 }
 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.
 