How do we manage state in react?
State Management
A component can either be stateful or stateless.
stateless component = JavaScript function or class that digests props as input.
class Hello extends React.Component {
render() {
return (
<div>
<h1>Hello, {this.props.username}</h1>
</div>
)
}
}
stateful component = JavaScript function or class that also initializes and maintains state, in the below example this.state is set to a object literal {} of date to new Date()
class Hello extends React.Component {
constructor(props) {
super(props)
this.state = { date: new Date() }
}
render() {
return (
<div>
<h1>Hello, {this.props.username}</h1>
<h2>It is {this.state.date.toDateString()}</h2>
</div>
)
}
}
So state is similar however it is private and fully controlled by the component. The component updates when state or props change. We should not ever update the state during the render of a component.
State Management for Functional Components
import React, { useState } from "react"
function Awesome() {
// Declare a new state variable of count for the onclick event below
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
)
}
We call useState method to track state within a functional component. This returns an array of value and a state update method
Updating State
You should always call setState for class components or state update method for functional components to update state.
Do not modify state directly as the component won’t render unless you are in the constructor.
// Correct way
this.setState({ comment: "Hello friend" })
// Incorrect way
this.state.comment = "Hello friend"
State updates may be asynchronous and thus both state and props may be updated asynchronously. Multiple setState calls may be batched but don’t rely on the their values to calculate the next state.
// Correct way
this.setState((state, props) => ({
counter: this.state.counter + this.props.increment,
}))
// Incorrect way - don't do this.
this.setState({
counter: this.state.counter + this.props.increment,
})
State Management
State updates via setState are merged but state updates via the hook method are not merged.
Class component
constructor(props) {
super(props);
this.state = { posts: [], comments: [] };
}
getData() {
fetchPosts().then(res =>
this.setState({
posts: res.posts
}));
fetchComments().then(res =>
this.setState({
comments: res.comments
}));
}
Function Component
const [data, setData] = useState({ posts: [], comments: [] })
getData = () => {
fetchPosts().then(res =>
setData({
...data,
posts: res.posts,
})
)
fetchComments().then(res =>
setData({
...data,
comments: res.comments,
})
)
}
- Use spread operator to set the existing properties
Conclusion 🐒
So with react and state, the data flows down, from top-down, parent to child. Neither parent nor child components can know if a certain component is stateful or stateless. So this state can be referred to as local or encapsulated state to the component, it is not accessible to any component other than the one that owns and sets it.
onwards and upwards! continue the journey…