102 lines
1.9 KiB
Markdown
102 lines
1.9 KiB
Markdown
![]() |
---
|
||
|
tags:
|
||
|
- typescript
|
||
|
- react
|
||
|
---
|
||
|
|
||
|
# Typing built-in hooks
|
||
|
|
||
|
## `useState`
|
||
|
|
||
|
```tsx
|
||
|
const [amount, setAmount] = useState<number | string>(3);
|
||
|
```
|
||
|
|
||
|
### With a ustom type
|
||
|
|
||
|
```tsx
|
||
|
interface IState {
|
||
|
people: IPerson[];
|
||
|
}
|
||
|
|
||
|
interface IPerson {
|
||
|
name: string;
|
||
|
age: number;
|
||
|
}
|
||
|
|
||
|
const [people, setPeople] = useState<IState>({});
|
||
|
|
||
|
// Alternative declaration
|
||
|
|
||
|
interface IState {
|
||
|
people: {
|
||
|
name: string;
|
||
|
age: number;
|
||
|
}[];
|
||
|
}
|
||
|
|
||
|
const [people, setPeople] = useState<IState["people"]>({});
|
||
|
```
|
||
|
|
||
|
## `useReducer`
|
||
|
|
||
|
Mostly the same. They key thing to type is the reducer function itself. You
|
||
|
don't need to type the intitial state unless it is a pre-existing type, you can
|
||
|
just use type assertion:
|
||
|
|
||
|
```jsx
|
||
|
interface IAction {
|
||
|
| { type: "increment"; payload: number }
|
||
|
| { type: "decrement"; payload: string };
|
||
|
}
|
||
|
|
||
|
const initialState = { count: 0 };
|
||
|
|
||
|
function reducer(state: typeof initialState, action: IAction) {
|
||
|
switch (action.type) {
|
||
|
case "increment":
|
||
|
return { count: state.count + action.payload };
|
||
|
case "decrement":
|
||
|
return { count: state.count - Number(action.payload) };
|
||
|
default:
|
||
|
throw new Error();
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Then the syntax is as normal, i.e:
|
||
|
|
||
|
```js
|
||
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||
|
```
|
||
|
|
||
|
## `useEffect`
|
||
|
|
||
|
> Limited potential for typing here as this hook does not return a value. See if
|
||
|
> there is useful inferred typing from use and update.
|
||
|
|
||
|
## `useContext`
|
||
|
|
||
|
We can use generics but mostly this is untyped:
|
||
|
|
||
|
```jsx
|
||
|
type Theme = "light" | "dark";
|
||
|
const ThemeContext = createContext < Theme > "dark";
|
||
|
|
||
|
const App = () => (
|
||
|
<ThemeContext.Provider value="dark">
|
||
|
<MyComponent />
|
||
|
</ThemeContext.Provider>
|
||
|
);
|
||
|
|
||
|
const MyComponent = () => {
|
||
|
const theme = useContext(ThemeContext);
|
||
|
return <div>The theme is {theme}</div>;
|
||
|
};
|
||
|
```
|
||
|
|
||
|
## `useCallback` / `useMemo`
|
||
|
|
||
|
You must only type the parameters that are passed to the callback, the return
|
||
|
value will be inferred.
|