In this lesson, we approach the concept of "prop drilling" and see how it can lead to maintenance pitfalls. By leveraging the Context API, we implement a context provider for our "search" and "shortlist" states. We then access that context where needed via the useContext
hook.
Simon Vrachliotis: [0:00] Our App is fairly small, but let's imagine it was a bit bigger. For some reason, the decision was made to break down the ShortList and NamePicker section of the App in its own component called namesContainer.
[0:11] The namesContainer component returns a <main> tag with the ShortList, NamePicker and ResetSearch components inside it. It requires five props to be passed to it, names for the list of names, as well as the state value and updater for both the searchValue and the shortList so it can pass them further onto its own children components.
[0:36] If we scroll up and down the App components, we start to see a lot of props passed around a few components deep. You can imagine how this can eventually become cumbersome. This pattern or undesired side effect of scope creep is called prop drilling.
[0:51] In this lesson, we look at an alternative way to share data instead between components, the context API.
[0:57] Let's take our names data to begin. Brought in at the root level of the App, pass down to the App component, pass down to the namesContainer component. From there, it's passed down to the ShortList and NamePicker components.
[1:15] Let's replace this drilling with the use of context. I'll create a new folder in src called providers. Inside, I'll create a file called names.js. I will import React, { createContext } from "react".
[1:30] Let's also import { names } from "../data". Our first step is to create a context, const NamesContext = createContext(). We will export that for now. NamesContext gives us two things, a provider and a consumer.
[1:48] Let's create a provider. I will export a function called NamesProvider() which takes children, and returns NamesContext.Provider with children inside of it. The value of the context we want to provide to the consumer will just be our names. We have exported two things, the context itself and the context provider component.
[2:13] Now, let's go in the App's root index.js and import our NamesProvider component. We will wrap the App component here with our NamesProvider component. Anything nested within this provider, aka the whole App here, will be able to consume the context value.
[2:31] Now the fun begins. Let's break the App for a minute by removing the names prop in the App component here. We'll also remove all instances of names prop passed in App.js.
[2:50] Let's go in NamePicker and implement the context consumer here. I'll remove the names prop as it's not being passed anymore. Instead, I will import the useContext Hook from React as well as our NamesContext from providers/names. Inside the NamePicker component, we can call the useContext Hook and pass it the NamesContext to retrieve our names.
[3:16] Let's do the same in ShortList. Import useContext, import the NamesContext, and the App works again. This is pretty nice. We avoided a bunch of hot potato in props through the App. We can do better though.