For context: At the start of the year I started planning and documenting a new solo project, called Pinpoint. Pinpoint is a goal tracker which allows users to create, sort and breakdown their goals so they are less overwhelming. This blog article is my latest documentation of building the project.
It’s fine to prop drill - at least when building Pinpoint. Since it’s a small application with only one or two layers, passing props directly isn’t an issue. In fact, as I’ll explain in this blog, I’m only passing props to components that actually use them, rather than just forwarding them further down the tree.
As I started building Pinpoint, I quickly realised how important it is to consider where state and functions are created. In this blog, I’ll share how I used parent state management and callback functions in child components to build Pinpoint’s core functionality. But before diving in, let me introduce the components I’ve created.
Components Overview
App - The parent component that manages the application state and renders child components.
AddGoal - A button component for adding new goals.
GoalForm - A form where users input goal details.
SavedGoal - Displays user-created goals.
Managing state in the Parent Component
Parent state management allows me to create and maintain the goals state in App.jsx (the parent component) and pass it down to AddGoal.jsx and SavedGoal.jsx via props:
goalData={goals}
goalData={goals[0]}
The goals state is initialised as an empty array, with new goals added to it over time. In AddGoal.jsx, I use a ternary operator to determine the button text based on whether any goals exist:
const buttonText = goalData.length > 0 ? "Add another goal": "Get started and create your first goal"
Meanwhile, in SavedGoal.jsx, the goals state is used to render the saved goal to the DOM:
<h2>{goalData.goalName}</h2>
Callback Functions for Child Components
I’ve used callback functions in child components to modify the goals state in the parent component. By passing functions from the parent as props, the child components can call them to update the goals state in App.jsx.
In GoalForm.jsx, the formData state stores the user’s goal details. When the user submits the form by clicking the save button, the saveGoal function is called, passing formData back to App.jsx. There, saveGoal updates the goals state using setGoals.
Similarly, in SavedGoal.jsx, the toDoData state stores the user's to-do list items for a saved goal. When the user adds an item, the saveToDoItem function is called, passing toDoData to App.jsx. In App.jsx, setGoals updates the goals state by mapping over the existing goals and adding the to-do list to the relevant one.
Reflecting back on this week
Overall, this week was a great learning experience! Focusing on parent state management and callback functions in Pinpoint further solidified my understanding of building applications with React. It also clarified why avoiding prop drilling is crucial in larger applications.
Top comments (1)
Great effort and good luck with pinpoint.