Recap →
State
→ It is a Collection of mutable values that can change over time.
- It is similar to the props whereas state can be changed but props can’t be changed.
Updating Existing State →
Earlier we are Just Changing/Altering the values of State but not changing them.
Let’s took an example u have a Scorekepper
component which Increases as which make the kills ⬇️
class Scorekeeper extends Component{
constructor(props){
super(props);
this.state = {score:0};
this.onKill = this.onKill.bind(this);
}
onKill(){
this.setState({score:this.state.state+1});
}
render(){
return(
<div>
<h1> Score is : {this.state.score} </h1>
<button onClick={this.onKill}>One KILL</button>
</div>
)
}
}
So every time we click on the button it will update the score by 1.
But, this is not the convenient way of doing this.
why??
Let’s have a look to the Below example In this we have button called Three kill
when we click on this Score only Increases by 1.
class Scorekeeper extends Component{
constructor(props){
super(props);
this.state = {score:0};
this.threeKill = this.threeKill.bind(this);
}
threeKill(){
this.setState({score:this.state.state+1});
this.setState({score:this.state.state+1});
this.setState({score:this.state.state+1});
}
render(){
return(
<div>
<h1> Score is : {this.state.score} </h1>
<button onClick={this.threeKill}>Three KILL</button>
</div>
)
}
}
But why this is not working ??
🎯 setState is Asynchronous is nature. So it is risky to assume that the previous call has finished. Also react will sometime batch(squash together) calls to setState together into one for Performance reasons.
- So as the all 3 calls were updating the same thing so on the priority basis the last one is only executed.
Look at this 👇
threeKill(){
this.setState({score: 100});
this.setState({score: 150});
}
The last call will run.
If a call to setState() depends on current state it’s better to use the “callbacks”
But What are the Callbacks ?
- They are the Function which are passed as a Argument to the another function.
**Like,**
function greet(name,callback){
const works = "Your work of Day is to plant the Trees"
const msg = `Good Morning ${name} ` + works;
callback(msg);
}
function log(msg){
console.log(msg);
}
greet("Jack" , log);
Like in this above example we passed the log function as the callback.
When the Greet function have completes it’s execution then at the end the log function is called.
When u pass the callback not pass it with the parenths cuz we don’t want to run it now.
Why we need Callbacks ??
When we are Requesting some data from the API or Database , we don’t know when the data will come , so all these process are called Asynchronous cuz they are not executed immediately.
So we pass the callbacks when the function executed the the callback is called and we came to know that it has been updated.
Same in the case of React the setState
method is Asynchronous so we can use the callbacks
threekill(){
this.setState(currState)=>{
return {state:currState+1}
}
this.setState(currState)=>{
return {state:currState+1}
}
this.setState(currState)=>{
return {state:currState+1}
}
}
IncTo3(currState){
return {state:currState+1};
}
threeKill(){
this.setState(this.IncTo3);
this.setState(this.IncTo3);
this.setState(this.IncTo3);
}
I know some of u are thinking that we can just do like this 😅
threeKill(){
this.setState({score:this.state.state+3});
}
But this only a example to tell u that If a call to setState() depends on current state it’s better to use the “callbacks”
.
Mutating State the safe Way →
- we can also define the Arrays in the state.
u have to be extra careful while modifying the Array.
Like I have a random Number Picker which picks out the Random name and keeps them.
class NumPicker extends Component{
static defaultProps = {
names : ["Jayant","Dushyant","Nitin","gaurav","kartik"]
}
constructor(props){
super(props);
this.state = {arr:["John ","sam "]}
}
Randomizer(){
const rand = Math.floor(Math.random()*this.props.names.length);
console.log(rand);
console.log(...this.state.arr,this.props.names[rand]);
//It will make a copy of the arr object with an extra name.
return this.setState({arr:[...this.state.arr,this.props.names[rand]]})
}
render(){
return(
<div>
<h1>Random Names are :{this.state.arr} </h1>
<button onClick={this.Randomizer}>Randomizer</button>
</div>
)
}
}
- So when u want to make changes in the Arrays , make a copy of the that and made changes in that and then pass it , to the setState.
For More Info u can Read this Article 👇
Handling State in React: Four Immutable Approaches to Consider
Designing State 😁
Down-ward Data Flow
- The parent has to be More Statefull.
The Parents should have the most of the state and they are passed using the state.
Let’s take an example of to-do list
It will have a To-do list
component , a To-do
component and in the To-do component their are many smaller Component. So what we can do is to keep all that changing data in state and pass it as a props.
Happy Coding 😄