If you have been developing an application that uses React, you might run into a situation where it becomes difficult or messy to manage the component props. A common scenario would be passing global data such as authenticated user details to deeply nested components.
Below is a simple example to demonstrate the passing of props from a top level component containing the userDetails
all the way to the child component that renders the details on a user profile page.
We have an App component with the authenticated user details (global data). For simplicity, we will define the userDetails
as a constant. We will have a component that look something similar to the following:
App.js
const App = () => {
const userDetails = {
name: "User1",
address: "NY",
status: "active",
dateJoined: "January 2019"
}
return (
<Profile userDetails={userDetails}/>
);
}
The App
component will render the Profile
component which will be the user profile page. In order for the userDetails
to be available on our profile screen, we pass it as a prop to the Profile
component.
Our Profile
component will like the following:
class Profile extends Component {
render() {
const { userDetails } = this.props
return (
<React.Fragment>
<PrimaryDetailsCard userDetails={userDetails} />
<SecondaryDetailsCard userDetails={userDetails} />
</React.Fragment>
)
}
}
Profile
component will render PrimaryDetailsCard
and SecondaryDetailsCard
component which carries diffrent kind of CSS styles for rendering different kinds of user details for the profile page. We once again have to pass userDetails
as a prop to PrimaryDetailsCard
and SecondaryDetailsCard
component.
Example of PrimaryDetailsCard
and SecondaryDetailsCard
code:
PrimaryDetailsCard.js
class PrimaryDetailsCard extends Component {
render() {
const { userDetails } = this.props
return (
<div>{userDetails.name}, {userDetails.dateJoined}</div>
)
}
}
SecondaryDetailsCard.js
class SecondaryDetailsCard extends Component {
render() {
const { userDetails } = this.props
return (
<div>{userDetails.address}</div>
)
}
}
The passing of props makes it hard to manage and it will get even more complex.
React.Context to the rescue!
We can avoid the hassle of passing props to multiple nested components especially if they do not need to know the details. We can use React.Context for that!
We start by declaring a UserContext
in a new file using the built in function const UserContext = React.createContext({});
.
Inside our example App.js
, simply import the UserContext
and use UserContext.Provider
to wrap all the components.
The provider simply allows the children component to receive the context value.
import UserContext from './UserContext';
const App = () => {
const userDetails = {
name: 'User1',
address: 'NY',
status: 'active',
dateJoined: 'January 2019',
};
return (
<UserContext.Provider value={userDetails}>
<Profile />
</UserContext.Provider>
)
};
Now that we have UserContext.Provider
set up with the userDetails
set as its value, our Profile
component does not need any knowledge regarding userDetails
, we can simply remove the codes relating to the userDetails
.
class Profile extends Component {
render() {
return (
<React.Fragment>
<PrimaryDetailsCard />
<SecondaryDetailsCard />
</React.Fragment>
);
}
}
The next part would be obtaining the context value inside our child component that are interested in the values. Using PrimaryDetailsCard
as an example:
import UserContext from './UserContext';
class PrimaryDetailsCard extends Component {
render() {
return (
<UserContext.Consumer>
{(userDetails) => {
return(
<div>
{userDetails.name}, {userDetails.dateJoined}
</div>
)
} }
</UserContext.Consumer>
);
}
}
We import the UserContext
and wrap our component with UserContext.Consumer
component. The Consumer
component will enable our component to access the value which was previously set by the Provider
. With that, we have organized our props neatly while displaying our User details on the profile page as usual!
You can learn more about React.Context
here
You can checkout my sample code on:
1) Without React.Context
2) Using React.Context
Top comments (0)