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 ================================================ Vite App
================================================ 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 (
) } 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 (

Number of cakes - {numOfCakes}

) } ================================================ 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 (

Number of ice creams - {numOfIcecreams}

setValue(parseInt(e.target.value))} />
) } ================================================ 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 (

List of Users

{user.loading &&
Loading...
} {!user.loading && user.error ?
Error: {user.error}
: null} {!user.loading && user.users.length ? ( ) : null}
) } ================================================ 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( , 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 ================================================ Vite App
================================================ 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 (
) } 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() export const useAppSelector: TypedUseSelectorHook = 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 // 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 (

Number of cakes - {numOfCakes}

) } ================================================ 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) => { 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 (

Number of ice creams - {numOfIcecreams}

setValue(parseInt(e.target.value))} />
) } ================================================ 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) => { 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 (

List of Users

{user.loading &&
Loading...
} {!user.loading && user.error ?
Error: {user.error}
: null} {!user.loading && user.users.length ? (
    {user.users.map(user => (
  • {user.name}
  • ))}
) : null}
) } ================================================ 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) => { 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( , document.getElementById('root') ) ================================================ FILE: react-rtk-ts-demo/src/vite-env.d.ts ================================================ /// ================================================ 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" } }