State is similar to Props. It's variables we can use in our components, with one key difference: Props can't change. State can.
Note: This section uses destructuring, feel free to go back and reread if you've forgotten how it works.
React.useState(
React.useState(
is what React calls a 'hook'. Hooks go inside your component functions, usually near the top of the function.
const Counter = (props) => {
const [count, setCount] = React.useState(0)
return <p>Hello</p>
}
Let's break down this line of code:
const [count, setCount] = React.useState(0)
// ^^^^^ ^^^^^^^^ ^
0
is the initial value of the piece of state we're setting up. In this case the number 0
.
count
is a const
which has the current value of that piece of state. You can talk about count
in your program.
setCount
is a function which sets the state (count
). If we want to update the state we call this function and pass the new value. e.g. setCount(5)
would set count
to 5.
Up until now the model of React is that your component functions get called once, return some JSX and React renders that JSX into the DOM and onto your screen!
With state this model needs adjusting:
React keeps track of props and state, if props or state change, it reruns your component function, calculates the JSX and keeps the DOM updated with the most up-to-date JSX for you.
In the example above you can see that the count
state is initially set to 0
and rendered onto the screen.
When the button is pressed the setCount(
function is called, this changes state causing react to rerender the component.
Upon rerender count
is now 1
.
Multiple state variables:
const Counter = (props) => {
const [count1, setCount1] = React.useState(0)
const [count2, setCount2] = React.useState(0)
return <div>
<p>{count1}</p>
<p>{count2}</p>
<button onClick={() => setCount1(count1 + 1)}>Add to 1</button>
<button onClick={() => setCount2(count2 + 1)}>Add to 2</button>
</div>
}
String state:
const Counter = (props) => {
const [string, setString] = React.useState("Hello")
return <div>
<p>{string}</p>
<input onChange={(e) => setString(e.target.value)} />
</div>
}
Array of objects:
const Counter = (props) => {
const [coders, setCoders] = React.useState([
{ name: 'Ada', born: 1816 },
{ name: 'Alice', born: 1990 },
{ name: 'Susan', born: 1960 },
])
return <div>
{coders.map(coder => <p>{coder.name}</p>)}
</div>
}
Let's go back to our Star
component from earlier on: <Stars stars={5} color="yellow" />
const Counter = (props) => {
const [stars, setStars] = React.useState(0)
return <div>
<Stars stars={stars} color="yellow" />
<button onClick={() => setStars(stars + 1)}>Add star</button>
</div>
}
Using state, each time the button is pressed the value of the stars=
prop increases by one. Whenever props change like this (via State) React rerenders calling any effected component functions again.