Geek Culture
Published in

Geek Culture

Using prevState with React, basic and complex

Photo by Karla Hernandez on Unsplash

How to use the famous “prevState” to modify our React state without overriding it !

Let start with a basic exemple (the -famous- counter) :

With a fresh new React App:

import "./App.css";
import React, { useState } from "react";
const App = () => {
const [mySuperCounter, setMySuperCounter] = useState(0);
const handleIncrement = () => {
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
};
const handleReset = () => {
setMySuperCounter(0);
};
return (
<div className="App">
<div>
<button
className="super-button"
type="submit"
onClick={handleIncrement}>
Incrementor
</button>
<button className="super-button" type="submit" onClick= {handleReset}>
State Resettor
</button>
</div>
<div>{mySuperCounter}</div>
</div>
);
};
export default App;

Ok here we have a basic component with a state “mySuperCounter”, and two button, one to increment, one to reset my state to 0.

If we look at the “handleIncrement” method we can think that the state will be incremented by 3 each time I click on my “Incrementor” button.

Instead of that we just increment by one. Why ? Cause our setState function will override the previous state to create a new one…So we’ll override 3 times our initial State by one, give us a magic result of ….one.

Now let’s have a look how we can add to the previous state :

I’ll just past my handleIncrement method here :

const handleIncrement = () => {
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
};

Here we go ! Now If we click on our “Incrementor” button we increment our counter by 3.

Why ? Because of our “prev” argument passed to the callback function of our setState.

In our case “prev” is equal to the previous State, so line by line we increment 0 by 1, 1 by 1, 2 by 1 => Result: 3

That’s for a basic example, let’s have a look on a more complex one !!

Add key/value from an array to an array of object:

Photo by Nick Fewings on Unsplash

Let’s simulate an API call with a promise:

// sections.jsconst mySections = () => {
return Promise.resolve([
{ id: 1, title: "My First Section" },
{ id: 2, title: "My Second Section" },
] );
};
export default mySections;

Then transform our App.js to make the call with a useEffect and store the result in a state:

// App.jsimport "./App.css";
import React, { useEffect, useState } from "react";
import mySections from "./sections";
const App = () => {
const [sections, setSections] = useState([]);
useEffect(() => {
const loadSections = async () => {
return await mySections();
};
loadSections().then((res) => {
setSections(res);
});
}, []);
return <div className="App"></div>;
};export default App;

Let’s create an other promise in an other file to simulate an other API call, we’ll receive data that we would like to dispatch in the sections above, depending on the section_id.

// tools.jsconst myTools = () => {
return Promise.resolve([
{ id: 1, title: "My Super first tools", section_id: 1 },
{ id: 2, title: "My Super second tools", section_id: 2 },
{ id: 3, title: "My Super third tools", section_id: 1 },
{ id: 4, title: "My Super fourth tools", section_id: 2 },
{ id: 5, title: "My Super fifth tools", section_id: 1 },
{ id: 6, title: "My Super sixth tools", section_id: 2 },
{ id: 7, title: "My Super seventh tools", section_id: 1 },
{ id: 8, title: "My Super eighth tools", section_id: 2 },
]);
};
export default myTools;

Then we have to modift ou App.js:

//App.jsconst App = () => {
const [sections, setSections] = useState([]);
useEffect(() => {
const loadSections = async () => {
return await mySections();
};
loadSections().then((res) => {
setSections(res);
});
const loadToolsIntoSections = async () => {
return await myTools();
};
loadToolsIntoSections().then((response) => {
setSections((prev) => {
return prev.map((section) => {
return {
...section,
tools: response.filter((tool) => {
return tool.section_id === section.id;
}),
};
});
});
});
}, []);
return <div className="App"></div>;
};
export default App;

Explanation:

We call the “loadToolsIntoSections” method, wich is an other API call simulation.

We re-use the setSections method and pass the “prev” argument to the callback. (we keep the previous state)

We map over the sections array to interact each object in it.

We use the spread operator to to create an other object, and we add an other key “tools”.

We use the response of ouf API Call to filter each tool where the section_id match with the id of the actual section.

By this way you can dispatch every tools inside their respective sections.

Hope this helps to understand how to use prevState easily !

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store