Before using React Context

A few months back, i started using react, most of us can relate to how it gets messy even before your app starts to get large, because you tend to keep passing down props till it gets to the inner components that’s needs it.

Though this is fine as it is just the way react works, but we wouldn’t want a behemoth of code, that is hard to maintain. usually , we would reach out to state management libraries(Redux/Mobx)/The New Context API 😜 — its getting old now. There are tonnes of tools nowadays that would make everything seem overwhelming but you’ve gotta know when to use them and you’ll be fine, else they make your waste more time and suck up your productivity. Trying to figure out how things work in context, Redux , Mobx or other libraries in general may not be an easy task too.

How do you eliminate props drilling?

Components Composition!
You can escape “props drilling” by passing down components as props so the components has the data it needs before its being passed down as prop. for the purpose of demonstration we would build a sample app 😜.

The Traditional App Structure will look like so :

<App>
<PageLayout/>
<NavigationBar>
<Avatar/>
</NavigationBar>
<Main>
….
</Main>
<PageLayout/>
</App>

Here the avatar component needs a user prop following the traditional way we would keep passing down a user prop till it gets to <Avatar/> like so:

<App>
<PageLayout user={user}/>
<NavigationBar user={user}>
<Avatar user={user}/>
</NavigationBar>
<Main/>
<PageLayout/>
</App>

Its feels redundant to pass down the user prop through many levels if in the end only the avatar component really needs it, Its also annoying that if the avatar component needs more props from the top you have to remember to add it in all intermediate levels too. So how do we compose our components to solve this problem?

Solution

<App>
<PageLayout>
<NavigationBar avatar={<Avatar user={this.state.user} />} />
<Main user={this.state.user}/>
</PageLayout>
</App>

Aha! i know what you are thinking — i didn’t formulate the idea even @dan_abramov tweeted about this and add a section to the ReactJS Docs

Lets Take a Look at The Complete Code

class App extends Component {
constructor(props) {
super(props);
this.state = {
user: {
name: “Prof. Yemi Osinbajo”,
image: “
https://i1.wp.com/techpoint.afric...",
position: “VICE PRESIDENT. NIGERIA”
}
}
}

render() {
return (
<AppWrapper>
<PageLayout>
<NavigationBar avatar={<Avatar user={this.state.user} />} />
<Main user={this.state.user}/>
</PageLayout>
</AppWrapper>
);
}
}

<AppWrapper> above is just a styled component, trying to style the app a lil bit you can see how we passed in the user prop to avatar component without letting most components know about it?

Other components Will look like so

const PageLayout = ({children}) => {
return (
<PageLayoutWrapper>
{children}
</PageLayoutWrapper>
);
}
const NavigationBar = ({avatar}) => {
return (
<NavbarWrapper>
{avatar}
</NavbarWrapper>
);
}
const Main = ({ user }) => { 
return (
<MainWrapper>
<Card>
<Image src={user.image} />
<UserInfo>
<UserName>{user.name}</UserName>
<UserPosition>{user.position}</UserPosition>
<Image small src={NG}/>
</UserInfo>
</Card>
</MainWrapper>
)
}
const Avatar = ({ user }) => {
return (
<Image small rounded src={user.image} />
)
}

That was pretty straight forward! , We pass components as props! and this saves us the whole prop drilling thing. However this should be used with care.

When then should React context be used

You should use context when same data needs to be accessible by many components in the tree and at different nested levels.Context let you broadcast such data and changes to all components below.

Feel free to check out the code

i am @marvinjudehk on twitter