How to Use State in React Components with TypeScript
Responses (0)
When you need to store some data that won't be shared across components you can use the local component state.
State in Functional Components#
To use state in functional component use useState
hook. This hook returns a tuple of two values. The first one is the current value of the state, the second one is a function to update the state.
import React, {useState} from 'react';
const Counter: React.FC = () => {
// value is the current value;
// setValue is an updater function;
// We can also pass an initial value
// into useState as an argument.
const [value, setValue] = useState(0);
return <>
<span>{value}</span>
<button
type="button"
// To update pass a new value
// into updater function:
onClick={() => setValue(value + 1)}>+
</button>
<button
type="button"
onClick={() => setValue(value - 1)}>-
</button>
</>
}
You can also increase type-safety declaring what types a state accepts:
import React, {useState} from 'react';
const Counter: React.FC = () => {
// useState is a generic function,
// that means that it can accept a type parameter.
// This type-parameter will tell TypeScript
// which types are acceptable for this state.
const [value, setValue] = useState<number>(0);
return (
<button
type="button"
// If we try to pass a string
// instead of a number we will get an error.
onClick={() => setValue('1')}
>
Set another value!
</button>
)
}
State in Class Components#
In class components, you can define a state as a class property called state
. With TypeScript, you can declare a type for the state:
import React from "react";
type CounterProps = {
header: string;
};
type CounterState = {
value: number;
};
class Counter extends React.Component<
CounterProps,
CounterState
> {
state: CounterState = {
value: 0,
};
render() {
const { header } = this.props;
const { value } = this.state;
return (
<div>
<h1>{header}</h1>
<p>{value}</p>
</div>
);
}
}
The CounterProps
type is used to declare what type the properties of this component support. The CounterState
type will check the state types at the pre-compile time, so you will know earlier if there is an error.
You don't have to annotate CounterState
the second time inside of a component itself, but it allows better type inference when accessing this.state.
Notice the React.Component<CounterProps, CounterState>
type. This is the generic React.Component
type. It takes two type-parameters that tell TypeScript how to interpret types of component props and state, so TypeScript can derive types of each field in props and the state.
There is no need to mark types fields readonly
since React.Component<P,S>
already marks them as immutable.
To change state in a class component use the setState
method. This method enqueues changes in the state and causes a component to re-render.
// ...
class Counter extends React.Component<
CounterProps,
CounterState
> {
state: CounterState = {
value: 0,
};
render() {
const { value } = this.state;
return (
<div>
<p>{value}</p>
<button
type="button"
onClick={this.setState(42)}
>
Set Another Value!
</button>
</div>
);
}
}