Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Revamp "Redux Essentials" tutorial to be TS-first and update contents #4706

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

markerikson
Copy link
Contributor

@markerikson markerikson commented May 12, 2024

Actual content changes for #4393 , at long last!

The current WIP example code is over in:

I'm doing another round of revisions and step-by-step checking to those code commits as I rework the tutorial content, but that should be the progression and code content I want to show off in the tutorial.

Big picture summary:

  • The entire example app is TS, start to finish
  • Improve some existing explanations
  • Cover some concepts that weren't included originally, like having multiple reducers handle one action
  • Cover newer APIs we didn't have in 2020, like createListenerMiddleware and thunks in createSlice
  • While not Redux-related, update some of the usage patterns like React Router 5 -> 6 and using uncontrolled inputs in forms instead of controlled

Copy link

codesandbox-ci bot commented May 12, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Copy link

netlify bot commented May 12, 2024

Deploy Preview for redux-docs ready!

Name Link
🔨 Latest commit 8aa8994
🔍 Latest deploy log https://app.netlify.com/sites/redux-docs/deploys/665e8498a62d55000857fa6f
😎 Deploy Preview https://deploy-preview-4706--redux-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

```ts title="features/posts/postsSlice.ts"
// highlight-start
// Import the `PayloadAction` TS type
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'

Explicit type imports could help better distinguish between TS/JS related material on a quick glance.

import { postAdded } from './postsSlice'
import { useAppDispatch } from '@/app/hooks'

import { type Post, postAdded } from './postsSlice'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { type Post, postAdded } from './postsSlice'
import type { Post } from './postsSlice'
import { postAdded } from './postsSlice'

More of a personal nitpick, feel free to ignore :)


Once we have the `dispatch` function available in our component, we can call `dispatch(postAdded())` in a click handler. We can take the title and content values from our React component `useState` hooks, generate a new ID, and put them together into a new post object that we pass to `postAdded()`.
Once we have the `dispatch` function available in our component, we can call `dispatch(postAdded())` in a click handler. We can take the title and content values from our form, generate a new ID, and put them together into a new post object that we pass to `postAdded()`.

```jsx title="features/posts/AddPostForm"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```jsx title="features/posts/AddPostForm"
```tsx title="features/posts/AddPostForm"

Not 100% sure if this should be tsx, but thought I'd mention it just in case.

```js title="features/posts/postsSlice.js"
```ts title="features/posts/postsSlice.ts"
// highlight-next-line
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'

```js title="features/users/usersSlice.js"
import { createSlice } from '@reduxjs/toolkit'
```ts title="features/users/usersSlice.ts"
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'

Since we can't just put a `Date` class instance into the Redux store, we'll track the `post.date` value as a timestamp string:
Since we can't just put a `Date` class instance into the Redux store, we'll track the `post.date` value as a timestamp string. We'll add it to the initial state values (using `date-fns` to subtract a few minutes from the current date and time), and also add it to each new post in the prepare callback

```ts title="features/posts/postsSlice.ts"=
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```ts title="features/posts/postsSlice.ts"=
```ts title="features/posts/postsSlice.ts"

```jsx title="features/posts/ReactionButtons.js"
import React from 'react'
```ts
import { createSlice, nanoid, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, nanoid, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice, nanoid } from '@reduxjs/toolkit'

In this case, our auth state is really just the current logged-in username, and we'll reset it to `null` if they log out.

```ts title="features/auth/authSlice.ts"
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'

Given that, we can import the `userLoggedOut` action from `authSlice.ts` into `postsSlice.ts`, listen for that action inside of `postsSlice.extraReducers`, and return an empty posts array to reset the posts list on logout:

```ts title="features/posts/postsSlice.ts"
import { createSlice, nanoid, PayloadAction } from '@reduxjs/toolkit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createSlice, nanoid, PayloadAction } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice, nanoid } from '@reduxjs/toolkit'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants