Skip to content

Commit

Permalink
docs: add tutorials/typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
crutchcorn committed Sep 13, 2024
1 parent 21876ce commit 68e438c
Showing 1 changed file with 33 additions and 40 deletions.
73 changes: 33 additions & 40 deletions docs/tutorials/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,29 @@ hide_title: true

 

# React Redux TypeScript Quick Start
# Angular Redux TypeScript Quick Start

:::tip What You'll Learn

- How to set up and use Redux Toolkit and React Redux with TypeScript
- How to set up and use Redux Toolkit and Angular Redux with TypeScript

:::

:::info Prerequisites

- Knowledge of React [Hooks](https://react.dev/reference/react#)
- Knowledge of Angular [Signals](https://angular.dev/guide/signals)
- Understanding of [Redux terms and concepts](https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow)
- Understanding of TypeScript syntax and concepts

:::

## Introduction

Welcome to the React Redux TypeScript Quick Start tutorial! **This tutorial will briefly show how to use TypeScript with Redux Toolkit and React-Redux**.
Welcome to the Angular Redux TypeScript Quick Start tutorial! **This tutorial will briefly show how to use TypeScript with Redux Toolkit and Angular-Redux**.

This page focuses on just how to set up the TypeScript aspects . For explanations of what Redux is, how it works, and full examples of how to use Redux, see [the Redux core docs tutorials](https://redux.js.org/tutorials/index).
This page focuses on just how to set up the TypeScript aspects. For explanations of what Redux is, how it works, and full examples of how to use Redux, see [the Redux core docs tutorials](https://redux.js.org/tutorials/index).

[React Redux](https://react-redux.js.org) is also written in TypeScript as of version 8, and also includes its own type definitions.

The [Redux+TS template for Create-React-App](https://github.com/reduxjs/cra-template-redux-typescript) comes with a working example of these patterns already configured.

:::info

The recently updated `@types/react@18` major version has changed component definitions to remove having `children` as a prop by default. This causes errors if you have multiple copies of `@types/react` in your project. To fix this, tell your package manager to resolve `@types/react` to a single version. Details:

https://github.com/facebook/react/issues/24304#issuecomment-1094565891

:::
[Angular Redux](/) is also written in TypeScript, and also includes its own type definitions.

## Project Setup

Expand Down Expand Up @@ -69,23 +59,23 @@ export type AppDispatch = typeof store.dispatch
// highlight-end
```
### Define Typed Hooks
### Define Typed Injectables
While it's possible to import the `RootState` and `AppDispatch` types into each component, it's **better to create typed versions of the `useDispatch` and `useSelector` hooks for usage in your application**. This is important for a couple reasons:
While it's possible to import the `RootState` and `AppDispatch` types into each component, it's **better to create typed versions of the `injectDispatch` and `injectSelector` injectables for usage in your application**. This is important for a couple reasons:
- For `useSelector`, it saves you the need to type `(state: RootState)` every time
- For `useDispatch`, the default `Dispatch` type does not know about thunks. In order to correctly dispatch thunks, you need to use the specific customized `AppDispatch` type from the store that includes the thunk middleware types, and use that with `useDispatch`. Adding a pre-typed `useDispatch` hook keeps you from forgetting to import `AppDispatch` where it's needed.
- For `injectSelector`, it saves you the need to type `(state: RootState)` every time
- For `injectDispatch`, the default `Dispatch` type does not know about thunks. In order to correctly dispatch thunks, you need to use the specific customized `AppDispatch` type from the store that includes the thunk middleware types, and use that with `injectDispatch`. Adding a pre-typed `injectDispatch` injectable keeps you from forgetting to import `AppDispatch` where it's needed.
Since these are actual variables, not types, it's important to define them in a separate file such as `app/hooks.ts`, not the store setup file. This allows you to import them into any component file that needs to use the hooks, and avoids potential circular import dependency issues.
Since these are actual variables, not types, it's important to define them in a separate file such as `app/injectables.ts`, not the store setup file. This allows you to import them into any component file that needs to use the injectables, and avoids potential circular import dependency issues.
```ts title="app/hooks.ts"
import { useDispatch, useSelector } from 'react-redux'
```ts title="app/injectables.ts"
import { injectDispatch, injectSelector } from '@reduxjs/angular-redux'
import type { RootState, AppDispatch } from './store'

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
// Use throughout your app instead of plain `injectDispatch` and `injectSelector`
export const injectAppDispatch = injectDispatch.withTypes<AppDispatch>()
export const injectAppSelector = injectSelector.withTypes<RootState>()
// highlight-end
```

Expand Down Expand Up @@ -154,29 +144,32 @@ const initialState = {
} as CounterState
```

### Use Typed Hooks in Components
### Use Typed Injectables in Components

In component files, import the pre-typed hooks instead of the standard hooks from React-Redux.

```tsx title="features/counter/Counter.tsx"
import React, { useState } from 'react'
In component files, import the pre-typed injectables instead of the standard injectables from Angular-Redux.

```typescript title="features/counter/counter.component.ts"
import { Component } from '@angular/core'
// highlight-next-line
import { useAppSelector, useAppDispatch } from 'app/hooks'

import { decrement, increment } from './counterSlice'
import { injectAppSelector, injectAppDispatch } from "app/injectables";
import { decrement, increment } from './store/counter-slice'

export function Counter() {
@Component({
selector: 'app-counter',
standalone: true,
// omit rendering logic
})
export class CounterComponent {
// highlight-start
// The `state` arg is correctly typed as `RootState` already
const count = useAppSelector((state) => state.counter.value)
const dispatch = useAppDispatch()
count = injectAppSelector(state => state.counter.value)
dispatch = injectAppDispatch()
// highlight-end

// omit rendering logic
increment = increment
decrement = decrement
}
```

## What's Next?

See [the "Usage with TypeScript" page](../using-react-redux/usage-with-typescript.md) for extended details on how to use Redux Toolkit's APIs with TypeScript.
See [the "Usage with TypeScript" page](../using-angular-redux/usage-with-typescript.md) for extended details on how to use Redux Toolkit's APIs with TypeScript.

0 comments on commit 68e438c

Please sign in to comment.