DEV Community

Cover image for React State Pattern | Day 8
Web.Developer.io
Web.Developer.io

Posted on

React State Pattern | Day 8

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.

Goals

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>
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

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>
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

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});
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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}
    }   
}
Enter fullscreen mode Exit fullscreen mode

State

IncTo3(currState){
    return {state:currState+1};
}

threeKill(){
    this.setState(this.IncTo3);
    this.setState(this.IncTo3);
    this.setState(this.IncTo3);
}
Enter fullscreen mode Exit fullscreen mode

I know some of u are thinking that we can just do like this 😅

threeKill(){
    this.setState({score:this.state.state+3});
}
Enter fullscreen mode Exit fullscreen mode

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”.

Setting State

Mutating State the safe Way →

Mutable

  • 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>
        )
    }

}
Enter fullscreen mode Exit fullscreen mode
  • 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.

React State Summary

React

For More Info u can Read this Article 👇

Handling State in React: Four Immutable Approaches to Consider

Designing State 😁

Designing
Minimizing State

React

React

React

Down-ward Data Flow

React

  • 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.

React Design

Happy Coding 😄

Discussion (4)

Collapse
martinpham profile image
Martin Pham

Cool guide. However you might want to try functional component with hooks also!

Just don’t forget to understand the differences between class component vs functional component. Each of them has pros and cons, depends on the requirements.

Collapse
lukeshiru profile image
Luke Shiru • Edited on

Ideally you should avoid using class components in 2022, the recommended way of doing components is using function components. Your last example then would look something like this:

import { useState } from "react";

// We add an util to get a random item from an array
const pickRandomItem = array => array[Math.floor(Math.random() * array.length)];

// The component itself
export const RandomNames = ({ names, onRandomClick }) => (
    <div>
        <h1>Random Names are: {names?.join(", ")}</h1>
        <button onClick={onRandomClick}>Randomizer</button>
    </div>
);

// We set a constant with the names to be used by the app
const defaultNames = [
    "Jayant",
    "Dushyant",
    "Nitin",
    "Gaurav",
    "Kartik",
    "John",
    "Sam",
];

// Finally, the app that has the state and passes it to the component:
export const App = () => {
    const [names, setNames] = useState([]);

    const handleRandomClick = () =>
        setNames([...names, pickRandomItem(defaultNames)]);

    return <RandomNames names={names} onRandomClick={handleRandomClick} />;
};
Enter fullscreen mode Exit fullscreen mode

Cheers!

Collapse
mnlfischer profile image
Manuel

Day 1: do not use class components.

Collapse
developerioweb profile image
Web.Developer.io Author

Day 8 Completed 🎉