State Initializer
Loading "Intro to State Initializer"
Run locally for transcripts
One liner: The state initializer pattern is a way to initialize (and
reset) the state of a component in a predictable way.
This one is simple in concept:
function useCounter() {
const [count, setCount] = useState(0)
const increment = () => setCount(c => c + 1)
return { count, increment }
}
If I wanted to initialize the state of the count to a different value, I could
do so by passing an argument to the
useCounter
function:function useCounter({ initialCount = 0 } = {}) {
const [count, setCount] = useState(initialCount)
const increment = () => setCount(c => c + 1)
return { count, increment }
}
And often when you have a state initializer, you also have a state resetter:
function useCounter({ initialCount = 0 } = {}) {
const [count, setCount] = useState(initialCount)
const increment = () => setCount(c => c + 1)
const reset = () => setCount(initialCount)
return { count, increment, reset }
}
But there's a catch. If you truly want to reset the component to its initial
state, then you need to make certain that any changes to the
initialCount
are
ignored!You can do this, by using a
ref
which will keep the initial value constant
across renders:function useCounter({ initialCount = 0 } = {}) {
const initialCountRef = useRef(initialCount)
const [count, setCount] = useState(initialCountRef.current)
const increment = () => setCount(c => c + 1)
const reset = () => setCount(initialCountRef.current)
return { count, increment, reset }
}
And that's the crux of the state initializer pattern.