Skip to content

Tutorials Section: Update code blocks with JS/TS toggle #1230

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

Merged
merged 5 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"checkJs": true,
"alwaysStrict": false,
"baseUrl": "..",
"jsx": "preserve",
"paths": {
"@reduxjs/toolkit": ["packages/toolkit/src/index.ts"],
"@reduxjs/toolkit/query": ["packages/toolkit/src/query/index.ts"],
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ 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.**

Expand Down
108 changes: 94 additions & 14 deletions docs/tutorials/quick-start.md → docs/tutorials/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.js"
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<typeof store.getState>
// 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.
Expand All @@ -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 `<Provider>` around our application in `src/index.js`. Import the Redux store we just created, put a `<Provider>` around your `<App>`, and pass the store as a prop:

```js title="index.js"
```ts title="index.js"
// file: App.tsx noEmit
import React from 'react'
export default function App() {
return <div>...</div>
}

// 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

Expand All @@ -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.js"
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
Expand All @@ -109,7 +134,7 @@ export const counterSlice = createSlice({
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
},
Expand All @@ -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.js"
// 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'
Expand All @@ -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 `<Counter>` component inside, then import that component into `App.js` and render it inside of `<App>`.

```jsx title="features/counter/Counter.js"
```ts title="features/counter/Counter.js"
// 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<typeof store.getState>

// 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
<Provider store={store}>
<Counter />
</Provider>,
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 (
Expand Down Expand Up @@ -208,7 +288,7 @@ The counter example app shown here is also the
Here's the complete counter application as a running CodeSandbox:

<iframe
class="codesandbox"
className="codesandbox"
src="https://codesandbox.io/embed/github/reduxjs/redux-essentials-counter-example/tree/master/?fontsize=14&hidenavigation=1&module=%2Fsrc%2Ffeatures%2Fcounter%2FcounterSlice.js&theme=dark&runonclick=1"
title="redux-essentials-example"
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
Expand Down
36 changes: 33 additions & 3 deletions docs/tutorials/rtk-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,27 @@ setupListeners(store.dispatch)

If you haven't already done so, follow the standard pattern for providing the Redux store to the rest of your React application component tree:

```tsx title="src/index.tsx"
```ts title="src/index.tsx"
// file: App.tsx noEmit
import React from 'react'
export default function App() {
return <div>...</div>
}

// file: app/store.ts noEmit
import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
reducer: {},
})

// file: index.tsx
import * as React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'

import App from './App'
import { store } from './store'
import store from './app/store'

const rootElement = document.getElementById('root')
render(
Expand All @@ -149,7 +163,23 @@ render(

Once a service has been defined, you can import the hooks to make a request.

```tsx title="src/App.tsx" no-transpile
```ts title="src/App.tsx"
// file: services/pokemon.ts noEmit
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query({
query: (name: string) => `pokemon/${name}`,
}),
}),
})

export const { useGetPokemonByNameQuery } = pokemonApi

// file: App.tsx
import * as React from 'react'
// highlight-next-line
import { useGetPokemonByNameQuery } from './services/pokemon'
Expand Down
72 changes: 36 additions & 36 deletions website/package.json
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
{
"name": "website",
"scripts": {
"start": "docusaurus start",
"build": "docusaurus build",
"netlify-build": "yarn install && yarn build",
"swizzle": "docusaurus swizzle",
"publish-gh-pages": "docusaurus deploy",
"deploy": "docusaurus deploy"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.1",
"@docusaurus/preset-classic": "2.0.0-beta.1",
"classnames": "^2.2.6",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-lite-youtube-embed": "^2.0.3",
"remark-typescript-tools": "^1.0.7",
"typescript": "~4.2.4"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"netlify-plugin-cache": "^1.0.3"
}
}
{
"name": "website",
"scripts": {
"start": "docusaurus start",
"build": "docusaurus build",
"netlify-build": "yarn install && yarn build",
"swizzle": "docusaurus swizzle",
"publish-gh-pages": "docusaurus deploy",
"deploy": "docusaurus deploy"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.1",
"@docusaurus/preset-classic": "2.0.0-beta.1",
"classnames": "^2.2.6",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-lite-youtube-embed": "^2.0.3",
"remark-typescript-tools": "^1.0.8",
"typescript": "~4.2.4"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"netlify-plugin-cache": "^1.0.3"
}
}