PageSourceSearch

https://mpolinowski.github.io/assets/js/c9c4ece2.6ac4af70.js

js mpolinowski.github.io collected 2026-10-03 09:38:45 UTC 20,444 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkmikes_dev_notebook=globalThis.webpackChunkmikes_dev_notebook||[]).push([[2699],{678722(e,n,t){t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit/index","title":"Redux Toolkit Github API","description":"Using the Redux Toolkit and AsyncThunk with Typescript & React","source":"@site/docs/Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit/index.md","sourceDirName":"Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit","slug":"/Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit/2023-12-18","permalink":"/docs/Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit/2023-12-18","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/Development/Javascript/2023-12-18-reactjs-typescript-redux-toolkit/index.md","tags":[{"inline":true,"label":"Javascript","permalink":"/docs/tags/javascript"},{"inline":true,"label":"React","permalink":"/docs/tags/react"}],"version":"current","sidebarPosition":5892,"frontMatter":{"sidebar_position":5892,"slug":"2023-12-18","title":"Redux Toolkit Github API","authors":"mpolinowski","tags":["Javascript","React"],"description":"Using the Redux Toolkit and AsyncThunk with Typescript & React"},"sidebar":"tutorialSidebar","previous":{"title":"React Query AsyncState Management","permalink":"/docs/Development/Javascript/2023-12-19-react-query-typescript/2023-12-19"},"next":{"title":"React Hooks Typescript","permalink":"/docs/Development/Javascript/2023-12-16-reactjs-hooks-typescript/2023-12-16"}}');var r=t(474848),i=t(28453);const o={sidebar_position:5892,slug:"2023-12-18",title:"Redux Toolkit Github API",authors:"mpolinowski",tags:["Javascript","React"],description:"Using the Redux Toolkit and AsyncThunk with Typescript & React"},a=void 0,c={},l=[{value:"Scaffolding",id:"scaffolding",level:2},{value:"Project Tracker",id:"project-tracker",level:2},{value:"Layout",id:"layout",level:3},{value:"Redux Store",id:"redux-store",level:3},{value:"Adding the Store",id:"adding-the-store",level:4},{value:"AsyncThunk API Calls",id:"asyncthunk-api-calls",level:3},{value:"Adding the API Call",id:"adding-the-api-call",level:4}];function p(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"TST, Hongkong",src:t(376442).A+"",width:"2359",height:"864"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#scaffolding",children:"Scaffolding"})}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#project-tracker",children:"Project Tracker"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#layout",children:"Layout"})}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#redux-store",children:"Redux Store"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#adding-the-store",children:"Adding the Store"})}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#asyncthunk-api-calls",children:"AsyncThunk API Calls"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#adding-the-api-call",children:"Adding the API Call"})}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"scaffolding",children:"Scaffolding"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"npm create vite@latest redux-toolkit\n\u2714 Select a framework: \u203a React\n\u2714 Select a variant: \u203a TypeScript + SWC\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cd redux-toolkit\nnpm install\nnpm install @mui/material @emotion/react @emotion/styled @fontsource/roboto \nnpm install @reduxjs/toolkit react-redux @types/react-redux @types/webpack-env\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"baseURL"})," to be able to work with absolute imports relative to the defined base:"]}
1),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./tsconfig.json"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n  "compilerOptions": {\n    "baseUrl": "./src",\n    ...\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"./vite.config.js"})," ",(0,r.jsx)(n.code,{children:"npm install vite-tsconfig-paths"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"import { defineConfig } from 'vite'\nimport tsconfigPaths from 'vite-tsconfig-paths'\nimport react from '@vitejs/plugin-react-swc'\n\nexport default defineConfig({\n  plugins: [\n    react(),\n    tsconfigPaths()\n  ],\n})\n"})}),"\n",(0,r.jsxs)(n.p,{children:["_",(0,r.jsx)(n.em,{children:"./src/pages/App.tsx"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"import Box from '@mui/material/Box';\nimport HelloWorld from 'components/HelloWorld'\n\nimport 'styles/App.css'\n\nexport default function App() {\n  \n  return (\n    <>\n        <Box sx={{ width: '100%', maxWidth: 1000 }}>\n          <HelloWorld greeting='Hello from React Typescript' />\n        </Box>\n    </>\n  )\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["_",(0,r.jsx)(n.em,{children:"./src/components/HelloWorld.tsx"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"import React from 'react'\nimport Typography from '@mui/material/Typography';\n\nimport { iHelloProps } from 'types/interfaces'\n\nexport default function HelloWorld({ greeting }: iHelloProps): React.JSX.Element {\n    return (\n        <Typography variant=\"h1\" gutterBottom>\n            { greeting }\n        </Typography>\n    )\n}\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"npm run dev\n"})}),"\n",(0,r.jsx)(n.h2,{id:"project-tracker",children:"Project Tracker"}),"\n",(0,r.jsx)(n.h3,{id:"layout",children:"Layout"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/components/ProjectCard.tsx"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:'import React from "react"\nimport { Typography, Grid, Stack, Paper} from "@mui/material"\n\ninterface IProps {\n    issueTitle: string\n}\n\nexport default function ProjectCard({ issueTitle }: IProps): React.JSX.Element {\n    return(\n        <div className="project_card">\n            <Paper elevation={1} sx={{p: \'10px\', m:\'1rem\'}}>\n                <Grid container spacing={2}>\n                    <Grid item xs={12} md={6}>\n                        <Stack spacing={2}>\n                            <Typography variant="h6" sx={{fontWeight: \'bold\'}}>\n                                Issue Title: {issueTitle}\n                            </Typography>\n                            <Stack direction=\'row\' spacing={2}>\n                                <Typography variant="body1">\n                                    Opened: yesterday\n                                </Typography>\n                                <Typography variant="body1">\n                                    Priority: medium\n                                </Typography>\n                            </Stack>\n                        </Stack>\n                    </Grid>\n                </Grid>\n            </Paper>\n        </div>\n    )\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/pages/App.tsx"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:'import React, { useState } from "react"\nimport { Box, Typography, TextField, Stack, Button } from "@mui/material"\n\nimport ProjectCard from "components/ProjectCard"\nimport HelloWorld from \'components/HelloWorld\'\n\nimport \'styles/App.css\'\n\n\nconst App = (): React.JSX.Element => {\n    const [textInput, setTextInput] = useState(\'\');\n    const handleTextInputChange = (e:any) => {\n        setTextInput(e.target.value);\n    };\n    return(\n        <div className="home_page">\n            <Box sx={{ml: \'5rem\', mr: \'5rem\'}}>\n              <HelloWorld greeting=\'Hello from React Typescript\' />\n                <Typography variant="h4" sx={{textAlign: \'center\'}}>\n                    Project Issue Tracker\n                </Typography>\n                <Box sx={{\n                  display: \'flex\',\n                  justifyContent: \'center\'\n                  }}>\n                    <Stack spacing={2}>\n                        <Typography variant="h5">\n                            Add new issue\n                        </Typography>\n                        <TextField \n                        id="outlined-basic" \n                        label="Title" \n                        variant="outlined" \n                        onChange={handleTextInputChange}\n                        value={textInput}\n                        />\n                        <Button variant="contained">Submit</Button>\n                    </Stack>\n                </Box>\n                <Box sx={{ml: \'1rem\', mt: \'3rem\'}}>\n                    <Typography variant="h5" >\n                        Opened issue\n                    </Typography>\n                        <ProjectCard issueTitle="Bug: Issue 1" />\n                        <ProjectCard issueTitle="Bug: Issue 2" />\n                </Box>\n            </Box>\n        </div>\n    )\n}\nexport default App\n'})}),"\n",(0,r.jsx)(n.h3,{id:"redux-store",children:"Redux Store"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/redux/issueReducer.ts"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { createSlice, PayloadAction } from \"@reduxjs/toolkit\"\n\nimport { IssueInitialState } from 'types/interfaces'\n\nconst initialState: IssueInitialState = {\n    projectIssues: []\n}\n\n\nexport const issueSlice = createSlice({\n    name: 'issue',\n    initialState,\n    reducers: {\n        addIssue: (state, action: PayloadAction<string>) =>
1 {\n            state.projectIssues = [...state.projectIssues, action.payload]\n        }\n    }\n})\n\n\nexport const { addIssue } = issueSlice.actions\nexport default issueSlice.reducer\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/redux/store.ts"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { configureStore } from '@reduxjs/toolkit'\n\nimport IssueReducer from \"redux/issueReducer\"\n\nexport const store = configureStore({\n    reducer: {\n        issue: IssueReducer\n    }\n})\nexport type RootState = ReturnType<typeof store.getState>\nexport type AppDispatch = typeof store.dispatch\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/main.tsx"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { Provider } from \"react-redux\"\nimport { store } from 'redux/store';\n\nimport App from 'pages/App.tsx'\nimport 'styles/index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n  <React.StrictMode>\n    <Provider store={store}>\n      <App />\n    </Provider>\n  </React.StrictMode>,\n)\n"})}),"\n",(0,r.jsx)(n.h4,{id:"adding-the-store",children:"Adding the Store"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:'import React, { useState } from "react"\nimport { Box, Typography, TextField, Stack, Button } from "@mui/material"\n\nimport ProjectCard from "components/ProjectCard"\nimport HelloWorld from \'components/HelloWorld\'\n\nimport { useDispatch, useSelector } from "react-redux"\nimport { RootState } from "redux/index"\nimport { addIssue } from "redux/issueReducer";\n\nimport \'styles/App.css\'\n\n\nconst App = (): React.JSX.Element => {\n    const [textInput, setTextInput] = useState(\'\')\n\n    const dispatch = useDispatch()\n    const issueList = useSelector((state: RootState) => state.issue.projectIssues)\n\n    const handleTextInputChange = (e:any) => {\n        setTextInput(e.target.value)\n    }\n\n    const handleClick = () => {\n      console.log(textInput)\n      dispatch(addIssue(textInput))\n      setTextInput(\'\')\n    }\n\n    return(\n        <div className="home_page">\n            <Box sx={{ml: \'5rem\', mr: \'5rem\'}}>\n              <HelloWorld greeting=\'Hello from React Typescript\' />\n                <Typography variant="h4" sx={{textAlign: \'center\'}}>\n                    Project Issue Tracker\n                </Typography>\n                <Box sx={{\n                  display: \'flex\',\n                  justifyContent: \'center\'\n                  }}>\n                    <Stack spacing={2}>\n                        <Typography variant="h5">\n                            Add new issue\n                        </Typography>\n                        <TextField \n                        id="outlined-basic" \n                        label="Title" \n                        variant="outlined" \n                        onChange={handleTextInputChange}\n                        value={textInput}\n                        />\n                        <Button variant="contained" onClick={handleClick}>Submit</Button>\n                    </Stack>\n                </Box>\n                <Box sx={{ml: \'1rem\', mt: \'3rem\'}}>\n                    <Typography variant="h5" >\n                        Opened issue\n                    </Typography>\n                    {\n                        issueList.map((issue) => {\n                            return(\n                                <ProjectCard key={issue} issueTitle={issue} />\n                            )\n                        })\n                    }\n                </Box>\n            </Box>\n        </div>\n    )\n}\n\nexport default App\n'})}),"\n",(0,r.jsx)(n.h3,{id:"asyncthunk-api-calls",children:"AsyncThunk API Calls"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/redux/ghIssueReducer.ts"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'\n\nimport { IssuesState }
1 from 'types/interfaces'\n\nexport const fetchIssues = createAsyncThunk<string[], void, { rejectValue: string }>(\n  \"githubIssue/fetchIssues\",\n  async (_, thunkAPI) => {\n    try {\n      const response = await fetch(\"https://api.github.com/repos/github/hub/issues\");\n      const data = await response.json();\n      const issues = data.map((issue: { title: string }) => issue.title);\n      return issues;\n    } catch (error) {\n      return thunkAPI.rejectWithValue(\"Failed to fetch issues.\");\n    }\n  }\n)\n\nconst initialState: IssuesState = {\n  issues: [],\n  loading: false,\n  error: null,\n}\n\nexport const issuesSliceGithub = createSlice({\n  name: 'github_issues',\n  initialState,\n  reducers: {},\n  extraReducers: (builder) => {\n    builder\n      .addCase(fetchIssues.pending, (state) => {\n        state.loading = true;\n        state.error = null;\n      })\n      .addCase(fetchIssues.fulfilled, (state, action) => {\n        state.loading = false;\n        state.issues = action.payload;\n      })\n      .addCase(fetchIssues.rejected, (state, action) => {\n        state.loading = false;\n        state.error = action.error.message || 'Something went wrong';\n      });\n  },\n})\n\nexport default issuesSliceGithub.reducer\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"./src/redux/store.ts"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { configureStore } from '@reduxjs/toolkit'\nimport { useDispatch } from 'react-redux'\n\nimport IssueReducer from \"redux/issueReducer\"\nimport GithubIssueReducer from 'redux/ghIssueReducer'\n\nexport const store = configureStore({\n    reducer: {\n        issue: IssueReducer,\n        githubIssue: GithubIssueReducer\n    }\n})\n\nexport type RootState = ReturnType<typeof store.getState>\nexport type AppDispatch = typeof store.dispatch\nexport const useAppDispatch = () => useDispatch<AppDispatch>()\n"})}),"\n",(0,r.jsx)(n.h4,{id:"adding-the-api-call",children:"Adding the API Call"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"import React, { useState, useEffect } from 'react'\nimport { useSelector } from 'react-redux'\nimport { Box, Typography, TextField, Stack, Button } from '@mui/material'\n\nimport ProjectCard from 'components/ProjectCard'\nimport HelloWorld from 'components/HelloWorld'\n\n\nimport { useAppDispatch, RootState, AppDispatch } from 'redux/store'\nimport { addIssue } from 'redux/issueReducer'\nimport { fetchIssues } from 'redux/ghIssueReducer'\n\nimport 'styles/App.css'\n\n\nconst App = (): React.JSX.Element => {\n    const dispatch: AppDispatch = useAppDispatch()\n    const [textInput, setTextInput] = useState('')\n\n    const githubIssueList = useSelector((state: RootState) => state.githubIssue.issues)\n    const loading = useSelector((state: RootState) => state.githubIssue.loading)\n    const error = useSelector((state: RootState) => state.githubIssue.error)\n\n    useEffect(() => {\n        dispatch(fetchIssues())\n      }, [dispatch])\n    \n    if (loading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return <div>Error: {error}</div>;\n    }\n\n    const handleTextInputChange = (e:any) => {\n        setTextInput(e.target.value)\n    }\n\n    const handleClick = () => {\n      console.log(textInput)\n      dispatch(addIssue(textInput))\n      setTextInput('')\n    }\n\n    return(\n        <div className=\"home_page\">\n            <Box sx={{ml: '5rem', mr: '5rem'}}>\n              <HelloWorld greeting='Hello from React Typescript' />\n                <Typography variant=\"h4\" sx={{textAlign: 'center'}}>\n                    Project Issue Tracker\n                </Typography>\n                <Box sx={{\n                  display: 'flex',\n                  justifyContent: 'center'\n                  }}>\n                    <Stack spacing={2}>\n                        <Typography variant=\"h5\">\n                            Add new issue\n                        </Typography>\n                        <TextField \n                        id=\"outlined-basic\" \n                        label=\"Title\" \n                        variant=\"outlined\" \n                        onChange={handleTextInputChange}\n                        value={textInput}\n                        />\n                        <Button variant=\"contained\" onClick={handleClick}>Submit</Button>\n                    </Stack>\n                </Box>\n                <Box sx={{ml: '1rem', mt: '3rem'}}>\n                    <Typography variant=\"h5\" >\n                        Opened issue\n                    </Typography>\n                    {\n                        githubIssueList?.map((issue : string) => {\n                            return(\n                                <ProjectCard key={issue} issueTitle={issue} />\n                            )\n                        })\n                    }\n                </Box>\n            </Box>\n        </div>\n    )\n}\n\nexport default App\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Redux Toolkit AsyncThunk Typescript",src:t(399587).A+"",width:"1372",height:"791"})})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},376442(e,n,t){const s=t.p+"assets/images/photo-kt443t6d_64hdh43hfh6dgjdfhg4_d-c3aedc7eed015cc5372c21f9c394693d.jpg";t.d(n,["A",0,s])},399587(e,n,t){const s=t.p+"assets/images/react-typescript_01-bf7334955c2a0a7dc4b51b23da4b3b8b.png";t.d(n,["A",0,s])},28453(e,n,t){t.d(n,{R:()=>o,x:()=>a});var s=t(296540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.