State
Contents
- Definition
- Usage in Functional Components
- Usage in Class-based Components
- Changing State without using
setState
doSomething()
after changing state- state change dependent on its previous value
Definition
- state is data that component owns or defines by itself
- The component owns the data and hence can be changed
- Similar to variables declared in TS files of angular components
Usage in Functional Components
Welcome.js
import React from 'react'
function Welcome(){
return(
<div>
<Greeting />
</div>
)
}
Defining State
Greeting.js
import React, { useState } from 'react'
function Greeting(){
// use 'useState' hook to define a state for component
const [message, setMessage] = useState('Welcome!');
return(
<div>
<p>{ message }</p>
</div>
)
}
Changing State
Greeting.js
import React, { useState } from 'react'
function Greeting(){
// use 'useState' hook to define a state for component
const [message, setMessage] = useState('Welcome!');
const capitalizeMessage = () => {
const message_copy = message;
setMessage(message_copy.toUpperCase());
}
return(
<div>
<p>{ message }</p>
<button
onClick = { capitalizeMessage }
>
Capitalize
</button>
</div>
)
}
- Read about
onClick
in Event Handling
Usage in Class-based Components
- React.Component class has props object as a property
Greeting.js
import React from 'react'
class Greeting extends React.Component{
constructor() {
super()
this.state = {
message: 'Welcome!'
}
}
render(){
// using 'message' property of 'state' object
const message = this.state.message
//OR
// using JavaScript destructuring
const { message } = this.state
return(
<div>
<p>{ message }</p>
</div>
)
}
}
Changing State
Greeting.js
...
capitalizeMessage() {
const capitalized_message = this.state.message.toUpperCase();
this.setState(
{
message : capitalized_message
}
)
}
...
Source : Codevolution Youtube
Changing State without using setState
note
NOTE:
- Changing state without using
setState
does NOT re-render the component. - In the below code count increments are logged to console correctly but since component won't render, count is always shown as 0 in the browser view
Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0)
const increase = () => {
count = count + 1
console.log(count)
}
return (
<div>
<p>{ count } </p>
<button onClick = { increase }>Increase</button>
</div>
)
}
export default Counter
doSomething()
after changing state
note
NOTE:
Class-based Components
- To
doSomething()
aftersetState
is called, use callback function as second parameter ofsetState
. - In the below code when message is logged to the console it is not capitalized. This is because setState is called asynchronously and in this case will be called when user clicks capitalized button. But console log statement shows the value that was present before the change has occurred, as console log is not run in the asynchronous call to setState.
Greeting.js
...
capitalizeMessage() {
const capitalized_message = this.state.message.toUpperCase();
this.setState(
{
message : capitalized_message
}
)
// ! logs NON-capitalized message to console
console.log(this.state.message)
}
...
Greeting.js
...
capitalizeMessage() {
const capitalized_message = this.state.message.toUpperCase();
this.setState(
{
message : capitalized_message
},
() => {
// callback function called whenever state changes
console.log(this.state.message)
}
)
}
...
Functional Components
Use
useEffect
hook and look for changes inmessage
state and act accordinglyRead
useEffect
in Life Cycle Methods
state change dependent on its previous value
note
NOTE:
- Use
prevState
if state depends on previous values - React groups state change functions for performance
- In the below case both
incrementCount()
functions are grouped and called together which results in count increasing by only +1 instead of +2
Counter.js
import React, { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
const incrementCount = () => {
setCount(count + 1);
// setCount(prevCount => prevCount + 1);
};
const incrementCountTwice = () => {
incrementCount();
incrementCount();
};
return (
<div>
<p>{count} </p>
<button onClick={ incrementCountTwice }>Increase</button>
</div>
);
}
- In
setCount()
method, use a function to which current count value is passed as argument
Counter.js
...
const incrementCount = () => {
setCount(
(prevCount) => {
return prevCount + 1
}
);
};
...