### Title: React TypeScript Cheat Sheet: Setting Types on Hooks
### Description:
This article provides a comprehensive guide for developers using React and TypeScript to set types on hooks effectively. It covers the basics of TypeScript type annotations for hooks, including useState, useEffect, and custom hooks.
### Content:
In the world of React development, utilizing TypeScript can significantly enhance your application's reliability and maintainability. One key aspect of this is setting types on hooks, which allows you to ensure that your components are using the hooks in the correct way and providing the expected types. This article serves as a quick reference guide to help you understand how to apply TypeScript type definitions to React hooks, including `useState`, `useEffect`, and even custom hooks.
#### 1. Using `useState` with Types
The `useState` hook is one of the most fundamental hooks used in React applications. It allows you to add state variables to functional components. To add types to `useState`, you can use the `React.useState` function from `@types/react`. Here’s an example:
```typescript
import { useState } from 'react';
// Correct usage with TypeScript type annotation
const MyComponent = () => {
const [count, setCount] = useState<number>(0); // Type annotation for useState
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};
export default MyComponent;
```
#### 2. Using `useEffect` with Types
`useEffect` is another essential hook for managing side effects such as subscriptions or DOM manipulations. When working with TypeScript, it's important to specify the types of dependencies and side effects. Here’s an example:
```typescript
import { useEffect, useState } from 'react';
// Correct usage with TypeScript type annotation
const MyComponent = () => {
const [count, setCount] = useState<number>(0);
useEffect(() => {
// Add a dependency array if necessary
const handleResize = () => {
console.log('Window resized');
};
window.addEventListener('resize', handleResize);
// Cleanup function to remove the event listener when the component unmounts
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // Empty array means this effect runs once after the initial render
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};
export default MyComponent;
```
#### 3. Custom Hooks with Types
Custom hooks are reusable pieces of logic that can be used across your application. Adding types to custom hooks ensures that they are called correctly and their parameters have the expected types. Here’s an example of a custom hook with types:
```typescript
import { useState, useEffect } from 'react';
// Define a custom hook with types
function useFetch<T>(url: string): { data: T; loading: boolean; error: any } {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
// Usage of the custom hook
const MyComponent = () => {
const { data, loading, error } = useFetch('https://api.example.com/data');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
export default MyComponent;
```
By following these examples and best practices, you can ensure that your React applications are robust and maintainable, especially when using TypeScript. Remember, thorough type annotations not only improve code readability but also catch potential bugs early in the development process.