From 181a54af9daf5144278b1ddbc3310a440242f394 Mon Sep 17 00:00:00 2001 From: Prince Raj Roy Date: Tue, 29 Jun 2021 21:06:34 +0530 Subject: [PATCH 1/4] Tutorials Section: Update code blocks with JS/TS toggle --- docs/api/createAsyncThunk.mdx | 2 +- docs/tsconfig.json | 1 + docs/tutorials/overview.md | 4 +- .../{quick-start.md => quick-start.mdx} | 108 +++++++++++++++--- docs/tutorials/rtk-query.mdx | 36 +++++- .../{typescript.md => typescript.mdx} | 52 +++++++-- docs/usage/usage-with-typescript.md | 4 +- website/package.json | 2 +- 8 files changed, 175 insertions(+), 34 deletions(-) rename docs/tutorials/{quick-start.md => quick-start.mdx} (78%) rename docs/tutorials/{typescript.md => typescript.mdx} (85%) diff --git a/docs/api/createAsyncThunk.mdx b/docs/api/createAsyncThunk.mdx index 068e525d87..ed76bc179e 100644 --- a/docs/api/createAsyncThunk.mdx +++ b/docs/api/createAsyncThunk.mdx @@ -19,7 +19,7 @@ It does not generate any reducer functions, since it does not know what data you :::tip -Redux Toolkit's [**RTK Query data fetching API**](../rtk-query/overview.md) is a purpose built data fetching and caching solution for Redux apps, and can **eliminate the need to write _any_ thunks or reducers to manage data fetching**. We encourage you to try it out and see if it can help simplify the data fetching code in your own apps! +Redux Toolkit's [**RTK Query data fetching API**](../rtk-query/overview.mdx) is a purpose built data fetching and caching solution for Redux apps, and can **eliminate the need to write _any_ thunks or reducers to manage data fetching**. We encourage you to try it out and see if it can help simplify the data fetching code in your own apps! ::: diff --git a/docs/tsconfig.json b/docs/tsconfig.json index ac2ce9def6..711b3110b8 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -16,6 +16,7 @@ "checkJs": true, "alwaysStrict": false, "baseUrl": "..", + "jsx": "preserve", "paths": { "@reduxjs/toolkit": ["src/index.ts"], "@reduxjs/toolkit/query": ["src/query/index.ts"], diff --git a/docs/tutorials/overview.md b/docs/tutorials/overview.md index 197e48677b..843c3b7da4 100644 --- a/docs/tutorials/overview.md +++ b/docs/tutorials/overview.md @@ -25,11 +25,11 @@ See these linked tutorials to learn how to use Redux Toolkit effectively. ## Redux Toolkit Quick Starts -The [**Redux Toolkit Quick Start tutorial**](./quick-start.md) briefly shows how to add and use Redux Toolkit in a React application. +The [**Redux Toolkit Quick Start tutorial**](./quick-start.mdx) briefly shows how to add and use Redux Toolkit in a React application. **If you just want the fastest way to get a basic example running, read the Quick Start tutorial.** -We also have a [**TypeScript Quick Start tutorial**](./typescript.md) that briefly shows how to set up and use TypeScript with Redux Toolkit and React-Redux. +We also have a [**TypeScript Quick Start tutorial**](./typescript.mdx) that briefly shows how to set up and use TypeScript with Redux Toolkit and React-Redux. ## Redux Essentials: A Real-World Example diff --git a/docs/tutorials/quick-start.md b/docs/tutorials/quick-start.mdx similarity index 78% rename from docs/tutorials/quick-start.md rename to docs/tutorials/quick-start.mdx index a931214196..f2d2f43bc1 100644 --- a/docs/tutorials/quick-start.md +++ b/docs/tutorials/quick-start.mdx @@ -49,12 +49,17 @@ npm install @reduxjs/toolkit react-redux Create a file named `src/app/store.js`. Import the `configureStore` API from Redux Toolkit. We'll start by creating an empty Redux store, and exporting it: -```js title="app/store.js" +```ts title="app/store.ts" import { configureStore } from '@reduxjs/toolkit' -export default configureStore({ +export const store = configureStore({ reducer: {}, }) + +// Infer the `RootState` and `AppDispatch` types from the store itself +export type RootState = ReturnType +// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} +export type AppDispatch = typeof store.dispatch ``` This creates a Redux store, and also automatically configure the Redux DevTools extension so that you can inspect the store while developing. @@ -63,13 +68,27 @@ This creates a Redux store, and also automatically configure the Redux DevTools Once the store is created, we can make it available to our React components by putting a React-Redux `` around our application in `src/index.js`. Import the Redux store we just created, put a `` around your ``, and pass the store as a prop: -```js title="index.js" +```ts title="index.tsx" +// file: App.tsx noEmit +import React from 'react' +export default function App() { + return
...
+} + +// file: app/store.ts noEmit +import { configureStore } from '@reduxjs/toolkit' + +export const store = configureStore({ + reducer: {}, +}) + +// file: index.tsx import React from 'react' import ReactDOM from 'react-dom' import './index.css' import App from './App' // highlight-start -import store from './app/store' +import { store } from './app/store' import { Provider } from 'react-redux' // highlight-end @@ -90,14 +109,20 @@ Creating a slice requires a string name to identify the slice, an initial state Redux requires that [we write all state updates immutably, by making copies of data and updating the copies](https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow#immutability). However, Redux Toolkit's `createSlice` and `createReducer` APIs use [Immer](https://immerjs.github.io/immer/) inside to allow us to [write "mutating" update logic that becomes correct immutable updates](https://redux.js.org/tutorials/fundamentals/part-8-modern-redux#immutable-updates-with-immer). -```js title="features/counter/counterSlice.js" -import { createSlice } from '@reduxjs/toolkit' +```ts title="features/counter/counterSlice.ts" +import { createSlice, PayloadAction } from '@reduxjs/toolkit' + +interface CounterState { + value: number +} + +const initialState: CounterState = { + value: 0, +} export const counterSlice = createSlice({ name: 'counter', - initialState: { - value: 0, - }, + initialState, reducers: { increment: (state) => { // Redux Toolkit allows us to write "mutating" logic in reducers. It @@ -109,7 +134,7 @@ export const counterSlice = createSlice({ decrement: (state) => { state.value -= 1 }, - incrementByAmount: (state, action) => { + incrementByAmount: (state, action: PayloadAction) => { state.value += action.payload }, }, @@ -125,7 +150,19 @@ export default counterSlice.reducer Next, we need to import the reducer function from the counter slice and add it to our store. By defining a field inside the `reducers` parameter, we tell the store to use this slice reducer function to handle all updates to that state. -```js title="app/store.js" +```ts title="app/store.ts" +// file: features/counter/counterSlice.ts noEmit +import { createSlice } from '@reduxjs/toolkit' + +const counterSlice = createSlice({ + name: 'counter', + initialState: {}, + reducers: {}, +}) + +export default counterSlice.reducer + +// file: app/store.ts import { configureStore } from '@reduxjs/toolkit' // highlight-next-line import counterReducer from '../features/counter/counterSlice' @@ -142,13 +179,56 @@ export default configureStore({ Now we can use the React-Redux hooks to let React components interact with the Redux store. We can read data from the store with `useSelector`, and dispatch actions using `useDispatch`. Create a `src/features/counter/Counter.js` file with a `` component inside, then import that component into `App.js` and render it inside of ``. -```jsx title="features/counter/Counter.js" +```ts title="features/counter/Counter.tsx" +// file: features/counter/counterSlice.ts noEmit +import { createSlice } from '@reduxjs/toolkit' +const counterSlice = createSlice({ + name: 'counter', + initialState: { + value: 0, + }, + reducers: { + increment: (state) => {}, + decrement: (state) => {}, + }, +}) + +export const { increment, decrement } = counterSlice.actions +export default counterSlice.reducer + +// file: app/store.ts noEmit +import { configureStore } from '@reduxjs/toolkit' +import counterReducer from '../features/counter/counterSlice' +export const store = configureStore({ + reducer: { + counter: counterReducer, + }, +}) +export type RootState = ReturnType + +// file: index.tsx noEmit +import React from 'react' +import ReactDOM from 'react-dom' +import { Counter } from './features/counter/Counter' +import { store } from './app/store' +import { Provider } from 'react-redux' + +ReactDOM.render( + // highlight-next-line + + + , + document.getElementById('root') +) + +// file: features/counter/Counter.tsx import React from 'react' +import { RootState } from '../../app/store' import { useSelector, useDispatch } from 'react-redux' import { decrement, increment } from './counterSlice' export function Counter() { - const count = useSelector((state) => state.counter.value) + const count = useSelector((state: RootState) => state.counter.value) const dispatch = useDispatch() return ( @@ -208,7 +288,7 @@ The counter example app shown here is also the Here's the complete counter application as a running CodeSandbox: