- what's props drilling?
- why to avoid it?
- How to dot that?
We are going to answer above questions to know about props drilling.
What's props drilling?
Passing props within a tree of components is known to be props drilling. Tree of components means when you pass prop from the root component App to the parent component Header of the child component Search.
App(props) --> Header(props) --> Search(props)
code for above example, shows how placeholder text is set upon the prop passed from root component.
import React from 'react'
export default function App(){
return(
<div>
<Header text="Search Movie..." />
</div>
)
}
function Header(props){
return(
<header>
<Search text={props.text} />
</header>
)
}
function Search(props){
return(
<nav>
<input
type='text'
value=''
placeholder={props.text}
/>
</nav>
)
}
keep drilling until you reach the bottom.
Why to avoid?
Before knowing the answer, look at the following picture.
It seems like every next doll is the child of previous doll, and you can hide all the dolls under the largest doll(root).
What if we want to put the coins in the last doll or in between? here's the catch! we will open the every doll until we open the wanted doll.
So, is the case with components that to change the props in last component we will pass props through every parent component and re-render it. which is quite expensive. that's why we need to avoid this props drilling.
How to avoid?
hmmmm, how to avoid? Well what the logic says is that there should be a global value which must be accessed wherever wanted, right! That's how it is also resolved.
Need 3 things
- Context component
- Provider
- Consumer
Context API is available to help us to provide and consume the context. Components accessing context will only be re-rendered.
Context component will be created by a built-in function of React React.createContext()
function by default takes a value, whatever you provide it.
Create context component
Make a new file, then export and import it.
const Context = React.createContext('default value')
export default Context
Providing
import the context first, then provide to component you want, suppose we are providing to Header component.
//import Context
<Context.Provider value='Search Movie...'>
<Header />
</Context.Provider>
Consuming
well context can be consumer by two way, either by React.Consumer or useContext() hook.
let's see the both
Context.Consumer
//import Context first, if it's a separate file.
<Context.Consumer>
{context => <input type='text' value='' placeholder={context} /> }
</Context.Consumer>
useContext() hook
you have to import {useContext} or use as React.useContext, it takes Context as an argument and returns the value.
<input type='text' value='' placeholder={useContext(Context)} />
Complete code
It's a functional component code so I have used hook.
import React, {useContext} from 'react'
const Context = React.createContext('default value')
export default function App(){
return(
<Context.Provider value='Seach Movie...'>
<Header />
</Context.Provider>
)
}
function Header(props){
return(
<header>
<Search />
</header>
)
}
function Search(props){
return(
<nav>
<Context.Consumer>
{context => (
<input
type='text'
value=''
placeholder={context}
/>
)
}
</Context.Consumer>
</nav>
)
}
Context API is the most common solution, but not the only.
Let me know if it helped you or if there's anything missing.
Join me on twitter @akramnarejo I keep sharing tips and resources about javascript, and react.
Top comments (3)
Thanks for the information! I would like to ask if the context could survive page refresh? Since in my project I use stores to store all global variables and they will be reset after page refresh.
Thanks in advance :)
Context doesn't save data on refresh, to achieve that you can save data to local storage, cookies, or session. If you are using redux for state management, there is redux-persist package that will do the same.
context doesn't have, what you are asking.