Introduction
If you pass props around to multiple components, where in some cases, the elements receiving them are not even using them, then you are prop drilling. It's like if you have 3 components A, B and C and you pass prop name
from component <A name="Tony" />
to component <B />
. But component B doesn't even use the name
prop. It simply passes it on to component C
where the prop is actually used.
Context API provided a mechanism to pass data through the component tree, without having the need to pass props manually down every level.
Let's begin with an example
import { useState } from "react";
const App = () => {
const [input, setInput] = useState("");
const inputHandler = (e) => setInput(e.target.value);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<label>Input </label>
<input value={input} onChange={inputHandler} />
</div>
);
};
Here we have a simple input box, where you can enter some text.
Let's refactor this component so that the state and the onChange handler are passed from the App component to another component called InputStuff.
import { useState } from "react";
const InputStuff = ({ input, inputHandler }) => {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<label>Input </label>
<input value={input} onChange={inputHandler} />
</div>
);
};
const App = () => {
const [input, setInput] = useState("");
const inputHandler = (e) => setInput(e.target.value);
return <InputStuff input={input} inputHandler={inputHandler} />;
};
The InputStuff needs a reference to the input
and inputHandler
state, so we're sending some props there. Let's refactor it once more to add another layer in our component tree.
import { useState } from "react";
const InputLabel = () => {
return <label>Input </label>;
};
const InputDisplay = ({ input, inputHandler }) => {
return <input value={input} onChange={inputHandler} />;
};
const InputStuff = ({ input, inputHandler }) => {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<InputLabel />
<InputDisplay input={input} inputHandler={inputHandler} />
</div>
);
};
const App = () => {
const [input, setInput] = useState("");
const inputHandler = (e) => setInput(e.target.value);
return <InputStuff input={input} inputHandler={inputHandler} />;
};
CodeSandbox URL showing the above code here
Voila this is prop drilling. To get the input
state and inputHandler
handler to the right places, we have to drill props through the InputStuff component. The InputStuff component itself doesn't actually need those props to function, but we have to still accept them and forward those props because its children need them.
Props drilling has both pros and cons. In a contrived example like this we do not have much issues, but once you have deeper layers and need some props everywhere, we can take advantage of the React Context API.
Here is the above example using React Context API
import React, { useState, useContext, createContext } from "react";
const InputContext = createContext();
const InputLabel = () => {
return <label>Input </label>;
};
const InputDisplay = () => {
const { input, inputHandler } = useContext(InputContext);
return <input value={input} onChange={inputHandler} />;
};
const InputStuff = ({ input, inputHandler }) => {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<InputLabel />
<InputDisplay input={input} inputHandler={inputHandler} />
</div>
);
};
const App = () => {
const [input, setInput] = useState("");
const inputHandler = (e) => setInput(e.target.value);
return (
<InputContext.Provider value={{ input, inputHandler }}>
<InputStuff input={input} inputHandler={inputHandler} />
</InputContext.Provider>
);
};
Here is the codesandbox ex using Context API here
Conclusion
- We understood props drilling and what the Context API are.
- Props Drilling by itself is fine and is useful to trace the path of how data flows, and hence eventually make refactoring and changes easy although this can spiral out of hand quite easily
- Context API can be used to share data that is considered global for React Components. It provides a mechanism to have props available at any level, without explicitly passing the props. It is ideally used for passing
Theme
,Locale
to many components in an application.
Top comments (0)