Note how setState() works. You pass it an object containing part(s) of the state you want to update. In other words, the object you pass would have keys corresponding to the keys in the component state, then setState() updates or sets the state by merging the object to the state. Thus, “set-State”. Remember how we said setState() works? Well, what if I told you that instead of passing an object, you could pass a function? To be super clear, passing object to setState() is not the problem here. The real problem is passing object to setState() when you want to calculate the next state from the previous state. So stop doing this. It’s not safe!
const App = () => {
const [state, setState] = React.useState({ first: "hello", second: "world" });
return (
<div>
<input type="text" value={state.first} onChange={(ev) => setState({...state, first: ev.target.value})} />
<input type="text" value={state.second} onChange={(ev) => setState({...state, second: ev.target.value})} />
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'))
React is a component based UI library. A component is basically a function that accept some properties and return a UI element.
function User(props) {
return <div>A pretty user</div>;
}
A component might need to have and manage its state. In that case, you usually write the component as a class. Then you have its state live in the class constructor
function:
class User {
constructor() {
this.state = { score: 0 };
}
render() {
return <div>This user scored {this.state.score}</div>;
}
}
Yes. setState()
also accepts a function. The function accepts the previous state and current props of the component which it uses to calculate and return the next state. See it below:
this.setState(function(state, props) {
return {
score: state.score - 1
};
});
What does React mean by this?
First, “multiple setState()
calls” could mean calling setState()
inside a single function more than once, like this:
state = {
score: 0
};
// multiple setState() calls
function increaseScoreBy3() {
this.setState({
score: this.state.score + 1
});
this.setState({
score: this.state.score + 1
});
this.setState({
score: this.state.score + 1
});
}
TL;DR: Functional setState is mainly helpful to expect correct state update when multiple setStates are triggered in a short interval of time where as conventional setState does reconciliation and could lead to unexpected state. React may batch multiple setState() calls into a single update for better performance. Now, your question mainly is probably whether to use setState with an object or with a function. Conventional setState VS Functional setState
First things first, in your case the two syntaxes are entirely different, what you might be looking for is the difference between
this.setState({
pictures: this.state.picture.concat(pics)
})
and
this.setState(prevState => ({
pictures: prevState.pictures.concat(pics)
}))
Consider the simple case, to understand this, in your function you might call setState()
more than once like:
myFunction = () => {
...
this.setState({
pictures: this.state.picture.concat(pics1)
})
this.setState({
pictures: this.state.picture.concat(pics1)
})
this.setState({
pictures: this.state.picture.concat(pics1)
})
...
}
Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form, instead:
this.setState((state) => {
return {
quantity: state.quantity + 1
};
});
People use both of them for different reasons, now the functional setState
is said to be safe because React
does something called a reconciliation process where in it merges multiple objects inside setState
when triggered frequently or concurrently and applies the changes in one shot, kind of like a batch process. This could potentially lead to some unexpected results in scenarios like below.
EXAMPLE:
increaseScoreBy3() {
this.setState({
score: this.state.score + 1
});
this.setState({
score: this.state.score + 1
});
this.setState({
score: this.state.score + 1
});
}
The state object of a component may contain multiple attributes and React allows using setState() function to update only a subset of those attributes as well as using multiple setState() methods to update each attribute value independently. Syntax: We can use setState() to change the state of the component directly as well as through an arrow function. setState is asynchronous call means if synchronous call get called it may not get updated at right time like to know current value of object after update using setState it may not get give current updated value on console. To get some behavior of synchronous need to pass function instead of object to setState.
setState({
stateName: updatedStateValue
})
// OR
setState((prevState) => ({
stateName: prevState.stateName + 1
}))
Step 1: Create a React application using the following command:
npx create - react - app foldername
Step 2: After creating your project folder i.e. foldername, move to it using the following command:
cd foldername
As you can see, we are passing an object to setState(). This object contains the part of the state we want to update which, in this case, is the value of greeting. React takes this value and merges it into the object that needs it. It’s just like the button component asks what it should use for updating the value of greeting and setState() responds with an answer.
import React, { Component } from 'react'
class App extends Component {
constructor(props){
super(props)
// Set initial state
this.state = {greeting :
'Click the button to receive greetings'}
// Binding this keyword
this.updateState = this.updateState.bind(this)
}
updateState(){
// Changing state
this.setState({greeting :
'PretagcodeForPretagcode welcomes you !!'})
}
render(){
return (
<div>
<h2>Greetings Portal</h2>
<p>{this.state.greeting}</p>
{/* Set click handler */}
<button onClick={this.updateState}>
Click me!
</button>
</div>
)
}
}
export default App;
Step to Run Application: Run the application using the following command from the root directory of the project:
npm start
What does useState return? It returns a pair of values: the current state and a function that updates it. This is why we write const [count, setCount] = useState(). This is similar to this.state.count and this.setState in a class, except you get them in a pair. If you’re not familiar with the syntax we used, we’ll come back to it at the bottom of this page. When we declare a state variable with useState, it returns a pair — an array with two items. The first item is the current value, and the second is a function that lets us update it. Using [0] and [1] to access them is a bit confusing because they have a specific meaning. This is why we use array destructuring instead. Line 4: Inside the Example component, we declare a new state variable by calling the useState Hook. It returns a pair of values, to which we give names. We’re calling our variable count because it holds the number of button clicks. We initialize it to zero by passing 0 as the only useState argument. The second returned item is itself a function. It lets us update the count so we’ll name it setCount.
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
const Example = (props) => {
// You can use Hooks here!
return <div />;
}
import React, {
useState
} from 'react';
function Example() {
// ...
}
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
When we use a function, it ensures that the state value is computed only once. This also helps in terms of performance improvement, specifically if the computation is expensive. React is essentially a component-based library. You can think of a component as a function which takes in some properties as input and outputs UI element(s). Now a component will need to manage it's own state. So, let's talk about the useState() hook. If we pass a function to React’s useState(), it would call that function and use the return value to initialize the state.
Basically, Hooks are a feature of React that allow us to hook functionality when using functional components. Here is how a basic functional component would look like;
import React, {useState} from "react";
const MyTestComponent = () => {
const [somevalue, setSomeValue] = useState(100);
return (
<div>
<p>{value}</p>
<button onClick={() => setSomeValue((somevalue + 1))}>Increment Some Value By 1</button>
</div>
);
};
The useState() hook allows us to set individual states. When we call useState(), we are kind of declaring a state variable and that state is actually retained between the different function calls. Thus, useState() gives a guarantee that the same value will be retained across renders. React has the ability to retain state values internally ensuring that the updated value is returned each time the function component runs.
The useState() hook accepts an input parameter which is used to set the initial state variable.
import React, {
useState
} from "react";
const MyTestComponent = () => {
const [somevalue, setSomeValue] = useState(100);
};
In the example above, the state value would get initialised to 100.
import React, {
useState
} from "react";
const MyTestComponent = () => {
console.log(“Example of passing
function to useState…”)
const functionForInitialState = () => 100;
const [somevalue, setSomeValue] = useState(functionForInitialState);
};
Thus, we can see that for any state updates that rely on the previous state value, we should use the functional variant of state update. The counter example in this case is one of the use cases in React and we need to know the previous count value and then add 10 in this case to return the new state. There can be other use cases like updating complex arrays/objects and where we would need to shallow copy the previous state value into new reference for the piece of state that we are going to update. If we simply want to replace the object/array and don't actually need the previous state, the regular state update should work fine as well.
Here is another example to show the difference between regular and functional variant of state updates.
import React, { useState } from "react";
import "./styles.css";
const App = () => {
const [counter, setCounter] = useState(100);
/**
* counter + 10 handler using the normal state update
*/
const handler1 = () => {
// assume counter equals some number num
setCounter(counter + 10); // update queued, counter === num, counter = num + 10 setCounter(counter + 10); // update queued, counter === num, counter = num + 10 setCounter(counter + 10); // update queued, counter === num, counter = num + 10 // when processed the counter will be num + 10
};
/**
* counter + 10 handler using functional state update
*/
const handler2 = () => {
// assume “counter” equals some number num
setCounter((counter) => counter + 10); // update is queued, counter === num + 0, counter = previouscounter + 10
setCounter((counter) => counter + 10); // update is queued, counter === num + 1, counter = previouscounter + 10
setCounter((counter) => counter + 10); // update is queued, counter === num + 2, counter = previouscounter + 10
// Here for each setState call, it uses the prior result and then updates the state to the new value // counter will be num + 10 + 10 + 10 OR num + 30
};
return (
<div className="App">
<h1>useState Example with Counter</h1>
<h2>Regular State Update V/s Functional State Update</h2>
counter: {counter}
<div>
<button type="button" onClick={handler1}>
+10 via the normal state update
</button>
<button type="button" onClick={handler2}>
+10 via the functional state update
</button>
</div>
</div>
);
};
export default App;
React programmers usually update state by passing an object that describes the changes we'd like to make. React then assigns the values and triggers an update. But what if I told you that you can pass a function to setState()? That's right, there's a functional side to React. Well, you can now prevent state updates and re-renders straight from setState(). You just need to have your function return null. For example, there is a maximum number of pizzas I can eat before I pass out. We don't want to continue updating and re-rendering after that point. There are many ways you can prevent that in React, but here's how you do it with functional setState(): This means you can decouple the state update logic from your components and export it to a new file to make it reusable and declarative. Sweet!
Here's how it works: You pass a function to setState()
that takes state
and props
as parameters and returns your desired state, which React will then use for the update. We go from this:
// Increase the numbers of pizzas I need to eat
this.setState({
pizzas: this.state.pizzas + 1
});
To this:
// Increase the number of pizzas I need to eat
function addAnotherPizza(state, props) {
return {
pizza: state.pizza + 1,
}
}
this.setState(addAnotherPizza);
const MAX_PIZZAS = 20;
function addAnotherPizza(state, props) {
// Stop updates and re-renders if I've had enough pizzas
if (state.pizza === MAX_PIZZAS) {
return null;
}
// If not, keep the pizzas coming
return {
pizza: state.pizza + 1,
}
}
this.setState(addAnotherPizza);
When the state is actually set can vary. Usually it happens on the next render, but it can sometimes be batched for performance. The setState function takes an optional callback parameter that can be used to make updates after the state is changed. This function will get called once the state has been updated, and the callback will receive the updated value of the state. To update the state of a component, you use the setState method. However it is easy to forget that the setState method is asynchronous, causing tricky to debug issues in your code. The setState function also does not return a Promise. Using async/await or anything similar will not work.
handleButtonClicked = evt => {
this.setState({
name: evt.currentTarget.value
})
this.props.callback(this.state.name) // Will send the old value for name
}
handleButtonClicked = evt => {
this.setState({
name: evt.currentTarget.value
}, () => {
this.props.callback(this.state.name)
})
}