Repository: gopinav/Redux-Toolkit-Tutorials
Branch: master
Commit: 3f0ba43e1dcf
Files: 46
Total size: 25.7 KB
Directory structure:
gitextract_isd_1pu8/
├── react-rtk-demo/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.css
│ │ ├── App.jsx
│ │ ├── app/
│ │ │ └── store.js
│ │ ├── features/
│ │ │ ├── cake/
│ │ │ │ ├── CakeView.jsx
│ │ │ │ └── cakeSlice.js
│ │ │ ├── icecream/
│ │ │ │ ├── IcecreamView.jsx
│ │ │ │ └── icecreamSlice.js
│ │ │ └── user/
│ │ │ ├── UserView.jsx
│ │ │ └── userSlice.js
│ │ ├── index.css
│ │ └── main.jsx
│ └── vite.config.js
├── react-rtk-ts-demo/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── app/
│ │ │ ├── hooks.ts
│ │ │ └── store.ts
│ │ ├── features/
│ │ │ ├── cake/
│ │ │ │ ├── CakeView.tsx
│ │ │ │ └── cakeSlice.ts
│ │ │ ├── icecream/
│ │ │ │ ├── IcecreamView.tsx
│ │ │ │ └── icecreamSlice.ts
│ │ │ └── user/
│ │ │ ├── UserView.tsx
│ │ │ └── userSlice.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── redux-demo/
│ ├── .gitignore
│ ├── asyncActions.js
│ ├── index.js
│ ├── nested-state.js
│ └── package.json
└── rtk-demo/
├── .gitignore
├── app/
│ └── store.js
├── features/
│ ├── cake/
│ │ └── cakeSlice.js
│ ├── icecream/
│ │ └── icecreamSlice.js
│ └── user/
│ └── userSlice.js
├── index.js
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: react-rtk-demo/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: react-rtk-demo/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
================================================
FILE: react-rtk-demo/package.json
================================================
{
"name": "react-rtk-demo",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^1.7.2",
"axios": "^0.26.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6"
},
"devDependencies": {
"@vitejs/plugin-react": "^1.0.7",
"vite": "^2.8.0"
}
}
================================================
FILE: react-rtk-demo/src/App.css
================================================
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
button {
font-size: calc(10px + 2vmin);
}
================================================
FILE: react-rtk-demo/src/App.jsx
================================================
import './App.css'
import { CakeView } from './features/cake/CakeView'
import { IcecreamView } from './features/icecream/IcecreamView'
import { UserView } from './features/user/UserView'
function App() {
return (
<div className='App'>
<CakeView />
<IcecreamView />
<UserView />
</div>
)
}
export default App
================================================
FILE: react-rtk-demo/src/app/store.js
================================================
import { configureStore } from '@reduxjs/toolkit'
import cakeReducer from '../features/cake/cakeSlice'
import icecreamReducer from '../features/icecream/icecreamSlice'
import userReducer from '../features/user/userSlice'
const store = configureStore({
reducer: {
cake: cakeReducer,
icecream: icecreamReducer,
user: userReducer
}
})
export default store
================================================
FILE: react-rtk-demo/src/features/cake/CakeView.jsx
================================================
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { ordered, restocked } from './cakeSlice'
export const CakeView = () => {
const numOfCakes = useSelector(state => state.cake.numOfCakes)
const dispatch = useDispatch()
return (
<div>
<h2>Number of cakes - {numOfCakes}</h2>
<button onClick={() => dispatch(ordered())}>Order Cake</button>
<button onClick={() => dispatch(restocked(5))}>Restock Cakes</button>
</div>
)
}
================================================
FILE: react-rtk-demo/src/features/cake/cakeSlice.js
================================================
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
numOfCakes: 20
}
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
ordered: state => {
state.numOfCakes--
},
restocked: (state, action) => {
state.numOfCakes += action.payload
}
}
})
export default cakeSlice.reducer
export const { ordered, restocked } = cakeSlice.actions
================================================
FILE: react-rtk-demo/src/features/icecream/IcecreamView.jsx
================================================
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { ordered, restocked } from './icecreamSlice'
export const IcecreamView = () => {
const [value, setValue] = React.useState(1)
const numOfIcecreams = useSelector(state => state.icecream.numOfIcecreams)
const dispatch = useDispatch()
return (
<div>
<h2>Number of ice creams - {numOfIcecreams}</h2>
<button onClick={() => dispatch(ordered())}>Order Ice cream</button>
<input
type='number'
value={value}
onChange={e => setValue(parseInt(e.target.value))}
/>
<button onClick={() => dispatch(restocked(value))}>
Restock Ice creams
</button>
</div>
)
}
================================================
FILE: react-rtk-demo/src/features/icecream/icecreamSlice.js
================================================
import { createSlice } from '@reduxjs/toolkit'
import { ordered as cakeOrdered } from '../cake/cakeSlice'
const initialState = {
numOfIcecreams: 10
}
const icecreamSlice = createSlice({
name: 'icecream',
initialState,
reducers: {
ordered: state => {
state.numOfIcecreams--
},
restocked: (state, action) => {
state.numOfIcecreams += action.payload
}
},
extraReducers: builder => {
builder.addCase(cakeOrdered, state => {
state.numOfIcecreams--
})
}
})
export default icecreamSlice.reducer
export const { ordered, restocked } = icecreamSlice.actions
================================================
FILE: react-rtk-demo/src/features/user/UserView.jsx
================================================
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchUsers } from './userSlice'
export const UserView = () => {
const user = useSelector(state => state.user)
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchUsers())
}, [])
return (
<div>
<h2>List of Users</h2>
{user.loading && <div>Loading...</div>}
{!user.loading && user.error ? <div>Error: {user.error}</div> : null}
{!user.loading && user.users.length ? (
<ul>
{user.users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : null}
</div>
)
}
================================================
FILE: react-rtk-demo/src/features/user/userSlice.js
================================================
import axios from 'axios'
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
const initialState = {
loading: false,
users: [],
error: ''
}
// Generates pending, fulfilled and rejected action types
export const fetchUsers = createAsyncThunk('user/fetchUsers', () => {
return axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => response.data)
})
const userSlice = createSlice({
name: 'user',
initialState,
extraReducers: builder => {
builder.addCase(fetchUsers.pending, state => {
state.loading = true
})
builder.addCase(fetchUsers.fulfilled, (state, action) => {
state.loading = false
state.users = action.payload
state.error = ''
})
builder.addCase(fetchUsers.rejected, (state, action) => {
state.loading = false
state.users = []
state.error = action.error.message
})
}
})
export default userSlice.reducer
================================================
FILE: react-rtk-demo/src/index.css
================================================
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
================================================
FILE: react-rtk-demo/src/main.jsx
================================================
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './app/store'
import './index.css'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
)
================================================
FILE: react-rtk-demo/vite.config.js
================================================
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()]
})
================================================
FILE: react-rtk-ts-demo/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: react-rtk-ts-demo/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
================================================
FILE: react-rtk-ts-demo/package.json
================================================
{
"name": "react-rtk-ts-demo",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^1.7.2",
"axios": "^0.26.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6"
},
"devDependencies": {
"@types/react": "^17.0.33",
"@types/react-dom": "^17.0.10",
"@vitejs/plugin-react": "^1.0.7",
"typescript": "^4.5.4",
"vite": "^2.8.0"
}
}
================================================
FILE: react-rtk-ts-demo/src/App.css
================================================
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
button {
font-size: calc(10px + 2vmin);
}
================================================
FILE: react-rtk-ts-demo/src/App.tsx
================================================
import './App.css'
import { CakeView } from './features/cake/CakeView'
import { IcecreamView } from './features/icecream/IcecreamView'
import { UserView } from './features/user/UserView'
function App() {
return (
<div className='App'>
<CakeView />
<IcecreamView />
<UserView />
</div>
)
}
export default App
================================================
FILE: react-rtk-ts-demo/src/app/hooks.ts
================================================
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
================================================
FILE: react-rtk-ts-demo/src/app/store.ts
================================================
import { configureStore } from '@reduxjs/toolkit'
import cakeReducer from '../features/cake/cakeSlice'
import icecreamReducer from '../features/icecream/icecreamSlice'
import userReducer from '../features/user/userSlice'
const store = configureStore({
reducer: {
cake: cakeReducer,
icecream: icecreamReducer,
user: userReducer
}
})
export default store
// 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
================================================
FILE: react-rtk-ts-demo/src/features/cake/CakeView.tsx
================================================
import { useAppSelector, useAppDispatch } from '../../app/hooks'
import { ordered, restocked } from './cakeSlice'
export const CakeView = () => {
const numOfCakes = useAppSelector(state => state.cake.numOfCakes)
const dispatch = useAppDispatch()
return (
<div>
<h2>Number of cakes - {numOfCakes}</h2>
<button onClick={() => dispatch(ordered())}>Order Cake</button>
<button onClick={() => dispatch(restocked(5))}>Restock Cakes</button>
</div>
)
}
================================================
FILE: react-rtk-ts-demo/src/features/cake/cakeSlice.ts
================================================
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
type InitialState = {
numOfCakes: number
}
const initialState: InitialState = {
numOfCakes: 20
}
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
ordered: state => {
state.numOfCakes--
},
restocked: (state, action: PayloadAction<number>) => {
state.numOfCakes += action.payload
}
}
})
export default cakeSlice.reducer
export const { ordered, restocked } = cakeSlice.actions
================================================
FILE: react-rtk-ts-demo/src/features/icecream/IcecreamView.tsx
================================================
import React from 'react'
import { useAppSelector, useAppDispatch } from '../../app/hooks'
import { ordered, restocked } from './icecreamSlice'
export const IcecreamView = () => {
const [value, setValue] = React.useState(1)
const numOfIcecreams = useAppSelector(state => state.icecream.numOfIcecreams)
const dispatch = useAppDispatch()
return (
<div>
<h2>Number of ice creams - {numOfIcecreams}</h2>
<button onClick={() => dispatch(ordered())}>Order Ice cream</button>
<input
type='number'
value={value}
onChange={e => setValue(parseInt(e.target.value))}
/>
<button onClick={() => dispatch(restocked(value))}>
Restock Ice creams
</button>
</div>
)
}
================================================
FILE: react-rtk-ts-demo/src/features/icecream/icecreamSlice.ts
================================================
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { ordered as cakeOrdered } from '../cake/cakeSlice'
type InitialState = {
numOfIcecreams: number
}
const initialState: InitialState = {
numOfIcecreams: 10
}
const icecreamSlice = createSlice({
name: 'icecream',
initialState,
reducers: {
ordered: state => {
state.numOfIcecreams--
},
restocked: (state, action: PayloadAction<number>) => {
state.numOfIcecreams += action.payload
}
},
extraReducers: builder => {
builder.addCase(cakeOrdered, state => {
state.numOfIcecreams--
})
}
})
export default icecreamSlice.reducer
export const { ordered, restocked } = icecreamSlice.actions
================================================
FILE: react-rtk-ts-demo/src/features/user/UserView.tsx
================================================
import { useEffect } from 'react'
import { useAppSelector, useAppDispatch } from '../../app/hooks'
import { fetchUsers } from './userSlice'
export const UserView = () => {
const user = useAppSelector(state => state.user)
const dispatch = useAppDispatch()
useEffect(() => {
dispatch(fetchUsers())
}, [])
return (
<div>
<h2>List of Users</h2>
{user.loading && <div>Loading...</div>}
{!user.loading && user.error ? <div>Error: {user.error}</div> : null}
{!user.loading && user.users.length ? (
<ul>
{user.users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : null}
</div>
)
}
================================================
FILE: react-rtk-ts-demo/src/features/user/userSlice.ts
================================================
import axios from 'axios'
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
type User = {
id: number
name: string
}
type InitialState = {
loading: boolean
users: User[]
error: string
}
const initialState: InitialState = {
loading: false,
users: [],
error: ''
}
// Generates pending, fulfilled and rejected action types
export const fetchUsers = createAsyncThunk('user/fetchUsers', () => {
return axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => response.data)
})
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: builder => {
builder.addCase(fetchUsers.pending, state => {
state.loading = true
})
builder.addCase(
fetchUsers.fulfilled,
(state, action: PayloadAction<User[]>) => {
state.loading = false
state.users = action.payload
state.error = ''
}
)
builder.addCase(fetchUsers.rejected, (state, action) => {
state.loading = false
state.users = []
state.error = action.error.message || 'Something went wrong'
})
}
})
export default userSlice.reducer
================================================
FILE: react-rtk-ts-demo/src/index.css
================================================
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
================================================
FILE: react-rtk-ts-demo/src/main.tsx
================================================
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './app/store'
import './index.css'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
)
================================================
FILE: react-rtk-ts-demo/src/vite-env.d.ts
================================================
/// <reference types="vite/client" />
================================================
FILE: react-rtk-ts-demo/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
================================================
FILE: react-rtk-ts-demo/tsconfig.node.json
================================================
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node"
},
"include": ["vite.config.ts"]
}
================================================
FILE: react-rtk-ts-demo/vite.config.ts
================================================
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()]
})
================================================
FILE: redux-demo/.gitignore
================================================
node_modules
================================================
FILE: redux-demo/asyncActions.js
================================================
const redux = require('redux')
const thunkMiddleware = require('redux-thunk').default
const axios = require('axios')
const createStore = redux.createStore
const applyMiddleware = redux.applyMiddleware
const initialState = {
loading: false,
users: [],
error: ''
}
const FETCH_USERS_REQUESTED = 'FETCH_USERS_REQUESTED'
const FETCH_USERS_SUCCEEDED = 'FETCH_USERS_SUCCEEDED'
const FETCH_USERS_FAILED = 'FETCH_USERS_FAILED'
const fetchUsersRequest = () => {
return {
type: FETCH_USERS_REQUESTED
}
}
const fetchUsersSuccess = users => {
return {
type: FETCH_USERS_SUCCEEDED,
payload: users
}
}
const fetchUsersFailure = error => {
return {
type: FETCH_USERS_FAILED,
payload: error
}
}
const fetchUsers = () => {
return function (dispatch) {
dispatch(fetchUsersRequest())
axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
// response.data is the users
const users = response.data.map(user => user.id)
dispatch(fetchUsersSuccess(users))
})
.catch(error => {
// error.message is the error message
dispatch(fetchUsersFailure(error.message))
})
}
}
const reducer = (state = initialState, action) => {
console.log(action.type)
switch (action.type) {
case FETCH_USERS_REQUESTED:
return {
...state,
loading: true
}
case FETCH_USERS_SUCCEEDED:
return {
loading: false,
users: action.payload,
error: ''
}
case FETCH_USERS_FAILED:
return {
loading: false,
users: [],
error: action.payload
}
}
}
const store = createStore(reducer, applyMiddleware(thunkMiddleware))
store.subscribe(() => {
console.log(store.getState())
})
store.dispatch(fetchUsers())
================================================
FILE: redux-demo/index.js
================================================
const redux = require('redux')
// const reduxLogger = require('redux-logger')
const createStore = redux.createStore
const bindActionCreators = redux.bindActionCreators
const combineReducers = redux.combineReducers
// const applyMiddleware = redux.applyMiddleware
// const logger = reduxLogger.createLogger()
const CAKE_ORDERED = 'CAKE_ORDERED'
const CAKE_RESTOCKED = 'CAKE_RESTOCKED'
const ICECREAM_ORDERED = 'ICECREAM_ORDERED'
const ICECREAM_RESTOCKED = 'ICECREAM_RESTOCKED'
function orderCake(qty = 1) {
return {
type: CAKE_ORDERED,
payload: qty
}
}
function restockCake(qty = 1) {
return {
type: CAKE_RESTOCKED,
payload: qty
}
}
function orderIceCream(qty = 1) {
return {
type: ICECREAM_ORDERED,
payload: qty
}
}
function restockIceCream(qty = 1) {
return {
type: ICECREAM_RESTOCKED,
payload: qty
}
}
// const initialState = {
// numOfCakes: 10,
// numOfIceCreams: 20
// }
const initialCakeState = {
numOfCakes: 10
}
const initialIceCreamState = {
numOfIceCreams: 20
}
// const reducer = (state = initialState, action) => {
// switch (action.type) {
// case CAKE_ORDERED:
// return {
// ...state,
// numOfCakes: state.numOfCakes - 1
// }
// case CAKE_RESTOCKED:
// return {
// ...state,
// numOfCakes: state.numOfCakes + action.payload
// }
// case ICECREAM_ORDERED:
// return {
// ...state,
// numOfIceCreams: state.numOfIceCreams - 1
// }
// case ICECREAM_RESTOCKED:
// return {
// ...state,
// numOfIceCreams: state.numOfIceCreams + action.payload
// }
// default:
// return state
// }
// }
const cakeReducer = (state = initialCakeState, action) => {
switch (action.type) {
case CAKE_ORDERED:
return {
...state,
numOfCakes: state.numOfCakes - 1
}
case CAKE_RESTOCKED:
return {
...state,
numOfCakes: state.numOfCakes + action.payload
}
default:
return state
}
}
const iceCreamReducer = (state = initialIceCreamState, action) => {
switch (action.type) {
case ICECREAM_ORDERED:
return {
...state,
numOfIceCreams: state.numOfIceCreams - 1
}
case ICECREAM_RESTOCKED:
return {
...state,
numOfIceCreams: state.numOfIceCreams + action.payload
}
case CAKE_ORDERED:
return {
...state,
numOfIceCreams: state.numOfIceCreams - 1
}
default:
return state
}
}
const rootReducer = combineReducers({
cake: cakeReducer,
iceCream: iceCreamReducer
})
// const store = createStore(rootReducer, applyMiddleware(logger))
const store = createStore(rootReducer)
console.log('Initial State ', store.getState())
const unsubscribe = store.subscribe(() => {
console.log('Updated State ', store.getState())
})
// store.dispatch(orderCake())
// store.dispatch(orderCake())
// store.dispatch(orderCake())
const actions = bindActionCreators(
{ orderCake, restockCake, orderIceCream, restockIceCream },
store.dispatch
)
actions.orderCake()
actions.orderCake()
actions.orderCake()
actions.restockCake(3)
actions.orderIceCream()
actions.orderIceCream()
actions.restockIceCream(2)
unsubscribe()
================================================
FILE: redux-demo/nested-state.js
================================================
const redux = require('redux')
const produce = require('immer').produce
const initialState = {
name: 'Vishwas',
address: {
street: '123 Main St',
city: 'Boston',
state: 'MA'
}
}
const STREET_UPDATED = 'STREET_UPDATED'
const updateStreet = street => {
return {
type: STREET_UPDATED,
payload: street
}
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case STREET_UPDATED:
// return {
// ...state,
// address: {
// ...state.address,
// street: action.payload
// }
// }
return produce(state, draft => {
draft.address.street = action.payload
})
default: {
return state
}
}
}
const store = redux.createStore(reducer)
console.log('Initial State ', store.getState())
const unsubscribe = store.subscribe(() => {
console.log('Updated State ', store.getState())
})
store.dispatch(updateStreet('456 Main St'))
unsubscribe()
================================================
FILE: redux-demo/package.json
================================================
{
"name": "redux-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.26.0",
"immer": "^9.0.12",
"redux": "^4.1.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.4.1"
}
}
================================================
FILE: rtk-demo/.gitignore
================================================
node_modules
================================================
FILE: rtk-demo/app/store.js
================================================
const configureStore = require('@reduxjs/toolkit').configureStore
// const reduxLogger = require('redux-logger')
const cakeReducer = require('../features/cake/cakeSlice')
const icecreamReducer = require('../features/icecream/icecreamSlice')
const userReducer = require('../features/user/userSlice')
// const logger = reduxLogger.createLogger()
const store = configureStore({
reducer: {
cake: cakeReducer,
icecream: icecreamReducer,
user: userReducer
}
// middleware: getDefaultMiddleware => getDefaultMiddleware().concat(logger)
})
module.exports = store
================================================
FILE: rtk-demo/features/cake/cakeSlice.js
================================================
const createSlice = require('@reduxjs/toolkit').createSlice
const initialState = {
numOfCakes: 20
}
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
ordered: state => {
state.numOfCakes--
},
restocked: (state, action) => {
state.numOfCakes += action.payload
}
}
})
module.exports = cakeSlice.reducer
module.exports.cakeActions = cakeSlice.actions
================================================
FILE: rtk-demo/features/icecream/icecreamSlice.js
================================================
const { cakeActions } = require('../cake/cakeSlice')
const createSlice = require('@reduxjs/toolkit').createSlice
const initialState = {
numOfIcecreams: 10
}
const icecreamSlice = createSlice({
name: 'icecream',
initialState,
reducers: {
ordered: state => {
state.numOfIcecreams--
},
restocked: (state, action) => {
state.numOfIcecreams += action.payload
}
},
extraReducers: builder => {
builder.addCase(cakeActions.ordered, state => {
state.numOfIcecreams--
})
}
// extraReducers: {
// ['cake/ordered']: state => {
// state.numOfIcecreams--
// }
// }
})
module.exports = icecreamSlice.reducer
module.exports.icecreamActions = icecreamSlice.actions
================================================
FILE: rtk-demo/features/user/userSlice.js
================================================
const axios = require('axios')
const createSlice = require('@reduxjs/toolkit').createSlice
const createAsyncThunk = require('@reduxjs/toolkit').createAsyncThunk
const initialState = {
loading: false,
users: [],
error: ''
}
// Generates pending, fulfilled and rejected action types
const fetchUsers = createAsyncThunk('user/fetchUsers', () => {
return axios
.get('https://jsonplaceholders.typicode.com/users')
.then(response => response.data.map(user => user.id))
})
const userSlice = createSlice({
name: 'user',
initialState,
extraReducers: builder => {
builder.addCase(fetchUsers.pending, state => {
state.loading = true
})
builder.addCase(fetchUsers.fulfilled, (state, action) => {
state.loading = false
state.users = action.payload
state.error = ''
})
builder.addCase(fetchUsers.rejected, (state, action) => {
state.loading = false
state.users = []
state.error = action.error.message
})
}
})
module.exports = userSlice.reducer
module.exports.fetchUsers = fetchUsers
================================================
FILE: rtk-demo/index.js
================================================
const store = require('./app/store')
const cakeActions = require('./features/cake/cakeSlice').cakeActions
const icecreamActions =
require('./features/icecream/icecreamSlice').icecreamActions
const fetchUsers = require('./features/user/userSlice').fetchUsers
console.log('Initial State ', store.getState())
const unsubscribe = store.subscribe(() => {
console.log('Updated State ', store.getState())
})
store.dispatch(cakeActions.ordered())
store.dispatch(cakeActions.ordered())
store.dispatch(cakeActions.ordered())
store.dispatch(cakeActions.restocked(3))
store.dispatch(icecreamActions.ordered())
store.dispatch(icecreamActions.ordered())
store.dispatch(icecreamActions.ordered())
store.dispatch(icecreamActions.restocked(3))
store.dispatch(fetchUsers())
// unsubscribe()
================================================
FILE: rtk-demo/package.json
================================================
{
"name": "rtk-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@reduxjs/toolkit": "^1.7.2",
"axios": "^0.26.0",
"redux-logger": "^3.0.6"
}
}
gitextract_isd_1pu8/
├── react-rtk-demo/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.css
│ │ ├── App.jsx
│ │ ├── app/
│ │ │ └── store.js
│ │ ├── features/
│ │ │ ├── cake/
│ │ │ │ ├── CakeView.jsx
│ │ │ │ └── cakeSlice.js
│ │ │ ├── icecream/
│ │ │ │ ├── IcecreamView.jsx
│ │ │ │ └── icecreamSlice.js
│ │ │ └── user/
│ │ │ ├── UserView.jsx
│ │ │ └── userSlice.js
│ │ ├── index.css
│ │ └── main.jsx
│ └── vite.config.js
├── react-rtk-ts-demo/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── app/
│ │ │ ├── hooks.ts
│ │ │ └── store.ts
│ │ ├── features/
│ │ │ ├── cake/
│ │ │ │ ├── CakeView.tsx
│ │ │ │ └── cakeSlice.ts
│ │ │ ├── icecream/
│ │ │ │ ├── IcecreamView.tsx
│ │ │ │ └── icecreamSlice.ts
│ │ │ └── user/
│ │ │ ├── UserView.tsx
│ │ │ └── userSlice.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── redux-demo/
│ ├── .gitignore
│ ├── asyncActions.js
│ ├── index.js
│ ├── nested-state.js
│ └── package.json
└── rtk-demo/
├── .gitignore
├── app/
│ └── store.js
├── features/
│ ├── cake/
│ │ └── cakeSlice.js
│ ├── icecream/
│ │ └── icecreamSlice.js
│ └── user/
│ └── userSlice.js
├── index.js
└── package.json
SYMBOL INDEX (20 symbols across 9 files)
FILE: react-rtk-demo/src/App.jsx
function App (line 6) | function App() {
FILE: react-rtk-ts-demo/src/App.tsx
function App (line 6) | function App() {
FILE: react-rtk-ts-demo/src/app/store.ts
type RootState (line 16) | type RootState = ReturnType<typeof store.getState>
type AppDispatch (line 18) | type AppDispatch = typeof store.dispatch
FILE: react-rtk-ts-demo/src/features/cake/cakeSlice.ts
type InitialState (line 3) | type InitialState = {
FILE: react-rtk-ts-demo/src/features/icecream/icecreamSlice.ts
type InitialState (line 4) | type InitialState = {
FILE: react-rtk-ts-demo/src/features/user/userSlice.ts
type User (line 4) | type User = {
type InitialState (line 8) | type InitialState = {
FILE: redux-demo/asyncActions.js
constant FETCH_USERS_REQUESTED (line 13) | const FETCH_USERS_REQUESTED = 'FETCH_USERS_REQUESTED'
constant FETCH_USERS_SUCCEEDED (line 14) | const FETCH_USERS_SUCCEEDED = 'FETCH_USERS_SUCCEEDED'
constant FETCH_USERS_FAILED (line 15) | const FETCH_USERS_FAILED = 'FETCH_USERS_FAILED'
FILE: redux-demo/index.js
constant CAKE_ORDERED (line 10) | const CAKE_ORDERED = 'CAKE_ORDERED'
constant CAKE_RESTOCKED (line 11) | const CAKE_RESTOCKED = 'CAKE_RESTOCKED'
constant ICECREAM_ORDERED (line 12) | const ICECREAM_ORDERED = 'ICECREAM_ORDERED'
constant ICECREAM_RESTOCKED (line 13) | const ICECREAM_RESTOCKED = 'ICECREAM_RESTOCKED'
function orderCake (line 15) | function orderCake(qty = 1) {
function restockCake (line 21) | function restockCake(qty = 1) {
function orderIceCream (line 27) | function orderIceCream(qty = 1) {
function restockIceCream (line 33) | function restockIceCream(qty = 1) {
FILE: redux-demo/nested-state.js
constant STREET_UPDATED (line 13) | const STREET_UPDATED = 'STREET_UPDATED'
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (31K chars).
[
{
"path": "react-rtk-demo/.gitignore",
"chars": 253,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": "react-rtk-demo/index.html",
"chars": 364,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
},
{
"path": "react-rtk-demo/package.json",
"chars": 418,
"preview": "{\n \"name\": \"react-rtk-demo\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"v"
},
{
"path": "react-rtk-demo/src/App.css",
"chars": 609,
"preview": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion:"
},
{
"path": "react-rtk-demo/src/App.jsx",
"chars": 340,
"preview": "import './App.css'\nimport { CakeView } from './features/cake/CakeView'\nimport { IcecreamView } from './features/icecream"
},
{
"path": "react-rtk-demo/src/app/store.js",
"chars": 371,
"preview": "import { configureStore } from '@reduxjs/toolkit'\nimport cakeReducer from '../features/cake/cakeSlice'\nimport icecreamRe"
},
{
"path": "react-rtk-demo/src/features/cake/CakeView.jsx",
"chars": 491,
"preview": "import React from 'react'\nimport { useSelector, useDispatch } from 'react-redux'\nimport { ordered, restocked } from './c"
},
{
"path": "react-rtk-demo/src/features/cake/cakeSlice.js",
"chars": 405,
"preview": "import { createSlice } from '@reduxjs/toolkit'\n\nconst initialState = {\n numOfCakes: 20\n}\n\nconst cakeSlice = createSlice"
},
{
"path": "react-rtk-demo/src/features/icecream/IcecreamView.jsx",
"chars": 721,
"preview": "import React from 'react'\nimport { useSelector, useDispatch } from 'react-redux'\nimport { ordered, restocked } from './i"
},
{
"path": "react-rtk-demo/src/features/icecream/icecreamSlice.js",
"chars": 607,
"preview": "import { createSlice } from '@reduxjs/toolkit'\nimport { ordered as cakeOrdered } from '../cake/cakeSlice'\n\nconst initial"
},
{
"path": "react-rtk-demo/src/features/user/UserView.jsx",
"chars": 682,
"preview": "import React, { useEffect } from 'react'\nimport { useSelector, useDispatch } from 'react-redux'\nimport { fetchUsers } fr"
},
{
"path": "react-rtk-demo/src/features/user/userSlice.js",
"chars": 937,
"preview": "import axios from 'axios'\nimport { createSlice, createAsyncThunk } from '@reduxjs/toolkit'\n\nconst initialState = {\n loa"
},
{
"path": "react-rtk-demo/src/index.css",
"chars": 366,
"preview": "body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Can"
},
{
"path": "react-rtk-demo/src/main.jsx",
"chars": 332,
"preview": "import React from 'react'\nimport ReactDOM from 'react-dom'\nimport { Provider } from 'react-redux'\nimport store from './a"
},
{
"path": "react-rtk-demo/vite.config.js",
"chars": 162,
"preview": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vitejs.dev/config/\nexport defau"
},
{
"path": "react-rtk-ts-demo/.gitignore",
"chars": 253,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": "react-rtk-ts-demo/index.html",
"chars": 364,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
},
{
"path": "react-rtk-ts-demo/package.json",
"chars": 524,
"preview": "{\n \"name\": \"react-rtk-ts-demo\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\":"
},
{
"path": "react-rtk-ts-demo/src/App.css",
"chars": 609,
"preview": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion:"
},
{
"path": "react-rtk-ts-demo/src/App.tsx",
"chars": 340,
"preview": "import './App.css'\nimport { CakeView } from './features/cake/CakeView'\nimport { IcecreamView } from './features/icecream"
},
{
"path": "react-rtk-ts-demo/src/app/hooks.ts",
"chars": 346,
"preview": "import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'\nimport type { RootState, AppDispatch } from"
},
{
"path": "react-rtk-ts-demo/src/app/store.ts",
"chars": 630,
"preview": "import { configureStore } from '@reduxjs/toolkit'\nimport cakeReducer from '../features/cake/cakeSlice'\nimport icecreamRe"
},
{
"path": "react-rtk-ts-demo/src/features/cake/CakeView.tsx",
"chars": 481,
"preview": "import { useAppSelector, useAppDispatch } from '../../app/hooks'\nimport { ordered, restocked } from './cakeSlice'\n\nexpor"
},
{
"path": "react-rtk-ts-demo/src/features/cake/cakeSlice.ts",
"chars": 502,
"preview": "import { createSlice, PayloadAction } from '@reduxjs/toolkit'\n\ntype InitialState = {\n numOfCakes: number\n}\nconst initia"
},
{
"path": "react-rtk-ts-demo/src/features/icecream/IcecreamView.tsx",
"chars": 737,
"preview": "import React from 'react'\nimport { useAppSelector, useAppDispatch } from '../../app/hooks'\nimport { ordered, restocked }"
},
{
"path": "react-rtk-ts-demo/src/features/icecream/icecreamSlice.ts",
"chars": 709,
"preview": "import { createSlice, PayloadAction } from '@reduxjs/toolkit'\nimport { ordered as cakeOrdered } from '../cake/cakeSlice'"
},
{
"path": "react-rtk-ts-demo/src/features/user/UserView.tsx",
"chars": 691,
"preview": "import { useEffect } from 'react'\nimport { useAppSelector, useAppDispatch } from '../../app/hooks'\nimport { fetchUsers }"
},
{
"path": "react-rtk-ts-demo/src/features/user/userSlice.ts",
"chars": 1176,
"preview": "import axios from 'axios'\nimport { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'\n\ntype User = {"
},
{
"path": "react-rtk-ts-demo/src/index.css",
"chars": 366,
"preview": "body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Can"
},
{
"path": "react-rtk-ts-demo/src/main.tsx",
"chars": 332,
"preview": "import React from 'react'\nimport ReactDOM from 'react-dom'\nimport { Provider } from 'react-redux'\nimport store from './a"
},
{
"path": "react-rtk-ts-demo/src/vite-env.d.ts",
"chars": 38,
"preview": "/// <reference types=\"vite/client\" />\n"
},
{
"path": "react-rtk-ts-demo/tsconfig.json",
"chars": 560,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"useDefineForClassFields\": true,\n \"lib\": [\"DOM\", \"DOM.Iterable\","
},
{
"path": "react-rtk-ts-demo/tsconfig.node.json",
"chars": 142,
"preview": "{\n \"compilerOptions\": {\n \"composite\": true,\n \"module\": \"esnext\",\n \"moduleResolution\": \"node\"\n },\n \"include\":"
},
{
"path": "react-rtk-ts-demo/vite.config.ts",
"chars": 162,
"preview": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vitejs.dev/config/\nexport defau"
},
{
"path": "redux-demo/.gitignore",
"chars": 12,
"preview": "node_modules"
},
{
"path": "redux-demo/asyncActions.js",
"chars": 1808,
"preview": "const redux = require('redux')\nconst thunkMiddleware = require('redux-thunk').default\nconst axios = require('axios')\ncon"
},
{
"path": "redux-demo/index.js",
"chars": 3273,
"preview": "const redux = require('redux')\n// const reduxLogger = require('redux-logger')\n\nconst createStore = redux.createStore\ncon"
},
{
"path": "redux-demo/nested-state.js",
"chars": 988,
"preview": "const redux = require('redux')\nconst produce = require('immer').produce\n\nconst initialState = {\n name: 'Vishwas',\n add"
},
{
"path": "redux-demo/package.json",
"chars": 378,
"preview": "{\n \"name\": \"redux-demo\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \"e"
},
{
"path": "rtk-demo/.gitignore",
"chars": 12,
"preview": "node_modules"
},
{
"path": "rtk-demo/app/store.js",
"chars": 575,
"preview": "const configureStore = require('@reduxjs/toolkit').configureStore\n// const reduxLogger = require('redux-logger')\nconst c"
},
{
"path": "rtk-demo/features/cake/cakeSlice.js",
"chars": 411,
"preview": "const createSlice = require('@reduxjs/toolkit').createSlice\n\nconst initialState = {\n numOfCakes: 20\n}\n\nconst cakeSlice "
},
{
"path": "rtk-demo/features/icecream/icecreamSlice.js",
"chars": 726,
"preview": "const { cakeActions } = require('../cake/cakeSlice')\n\nconst createSlice = require('@reduxjs/toolkit').createSlice\n\nconst"
},
{
"path": "rtk-demo/features/user/userSlice.js",
"chars": 1063,
"preview": "const axios = require('axios')\nconst createSlice = require('@reduxjs/toolkit').createSlice\nconst createAsyncThunk = requ"
},
{
"path": "rtk-demo/index.js",
"chars": 778,
"preview": "const store = require('./app/store')\nconst cakeActions = require('./features/cake/cakeSlice').cakeActions\nconst icecream"
},
{
"path": "rtk-demo/package.json",
"chars": 316,
"preview": "{\n \"name\": \"rtk-demo\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \"ech"
}
]
About this extraction
This page contains the full source code of the gopinav/Redux-Toolkit-Tutorials GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (25.7 KB), approximately 8.5k tokens, and a symbol index with 20 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.