Rem Kim - 2020-04-18
I bet everyone who works with React on day to day basis knows what it "Props Drilling". Passing props down the component tree can become quite a burden. Hers is how Context API can solve that problem!
Lets look at this example component
As you can see,
Dashboard is a sort of a Controller component that manages state using
React.useReducer. It passes actions down to child components.
In some cases this is absolutely fine. However as your application grows you may run into a situation when most distant child needs state or an action from root parent component.
<RootParent> <NestedChild> <DeeperNestedChild> < TheDeepestChildThatNeedsState /> </DeeperNestedChild> </NestedChild> </RootParent>
This is called "Props Drilling". Passing props down the component tree to child that needs it.
As a developer I try to recognize moments like that because maintaining that type of code in the future will be very hard. Thankfully its never too late to refactor! Well, I hope...
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
Now lets see how we can refactor our example to utilize Context API.
First of all lets understand how it works.
You can create Context using
React.createContext and pass default value of the context. Once that is done you can wrap your components with ContextProvider, hence making its value available across every child component. Neat right?!
Now let's come back to our example and refactor it using Context API and React Hooks.
Define all actions in actions.js pay attention that it exports function that requires
dispatch prop in order to trigger an action and exports function wrapper around dispatch.
Corresponding reducers in reducers.js. It contains our
reducers function to handle state updates.
Connecting actions and reducers in simple yet elegant hook useData.js that will export state and actions.
Now lets put utility function that will create context and export
useCtx hook and Context Provider in createCtx.js
Here is where all the magic happens contextApi.jsx.
Let's break this one down.
First we create context using
createCtx() and export hook
useDataContext this will be used in child components to get access to state and actions.
Second we export
DataProvider that will wrap child components and utilize our
useData hook that will create our state from reducers and actions.
Clean isn't it? No props are being passed to child components.
Here is Filters.js example on how to consume state and grab action from the Context
If you want to play around with example here is the Link
Obviously its up to you how you want to manage state in your application and what state management architecture suits your case. But if you faced "Props Drilling" problem, I think Context API is the way to go!