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 ? (
{user.users.map(user => (
- {user.name}
))}
) : 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"
}
}