ReactJS Context Part 5

Hıdır Volkan Sönmez
3 min readJan 31, 2024

Context” ensures that the required data is used “globally” within the application. Let’s continue with the previous game example.

The player has more than one skill and we should not allow him to use one skill while using another. So we’ll start by setting the “isBusy” state for the player. Additionally, when the player uses the ability, we want the action to complete after a certain amount of time, for example it could be 2 seconds.

Let’s add “isBusy” state to the “constructor” section of our <Game> component.

constructor(props){
super(props);
this.handleSkillPoint = this.handleSkillPoint.bind(this);
this.state = {
skills: props.user.skills,
bag: props.user.bag,
isBusy: false
}
}

I set the initial value of the “isBusy” status to “false”.

Now let’s make it take 2 seconds for the skill to complete. For this, I will make changes to the “handleSkillPoint” method in the <Game> component.

handleSkillPoint(skillName, skillPointValue){
this.setState({
isBusy: true
});
setTimeout(() => {
let userSkills = this.state.skills;
userSkills[skillName].point = skillPointValue;
this.setState({
skills: userSkills,
isBusy: false
});
}, 2000);
}

When the player used the ability, I updated the “state” section of the <Game> component and set the “isBusy” state to “true”, the player is now determined to be busy. I also included the skill score increase process that I performed within the method in a “setTimeout” function, so that the skill will increase the score after 2 seconds. At the end of the process, I set the player’s “isBusy” status to “false”.

this.setState({
skills: userSkills,
isBusy: false
});

What we need to do now is to ensure that when the “Start Product” button in the <Skill> component is clicked, all “Start Product” buttons are “disabled” while the skill runs for 2 seconds. For this, I create a “context” in “index.js” (BusyContext).

const BusyContext = React.createContext(false);

I set the initial value of BusyContext to “false”. Our context is ready to use.

Context has two APIs “Provider” and “Consumer”.

Provider: It takes a value as “property” and transfers this value to its subcomponents.

Consumer: Allows us to return a result by writing a function inside it.

Let’s send the “isBusy” value to the child components by adding “Provider” to the “return” section of our <Game> component.

return(
<div className=”game”>
<Header userMoney={this.props.user.money}/>
<BusyContext.Provider value={this.state.isBusy}>
<SkillList skills={this.props.user.skills} handleSkillPoint={this.handleSkillPoint}/>
</BusyContext.Provider>
</div>
);

I took the <SkillList> component into <BusyContext> and sent the “isBusy” status of the <Game> component as “property” and “value” in <BusyContext>. <SkillList> and all other components below it will now be aware of the “isBusy” status.

Now let’s determine how our button will look according to the “isBusy” state.

return(
<li className=”skill”>
<span>{this.props.skill.name} : </span>
<span>{this.props.skill.point}</span>
<div>Product: {this.props.skill.product}</div>
<BusyContext.Consumer>
{value => {
if (value) {
return <button disabled>Busy</button>
}
return <button onClick={this.clickHandle}>Start Product</button>
}}
</BusyContext.Consumer>
</li>
);

I placed the section where the button is rendered in <BusyContext.Consumer>. I created a function here and it takes the “value” of <BusyContext> as a “parameter”. If the incoming “value” is “true”, I render a “disabled” button. If not, the button to which we assigned the “clickHandle” event on the bottom line will be rendered, since it will not go into the if anyway.

As a result, when the player clicks on the “Start Product” button, the process will be executed for 2 seconds and the “busy” button will appear during this process.

--

--