国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(五) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(二十)

這篇具有很好參考價(jià)值的文章主要介紹了【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(五) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(二十)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


學(xué)習(xí)內(nèi)容來源:React + React Hook + TS 最佳實(shí)踐-慕課網(wǎng)


相對原教程,我在學(xué)習(xí)開始時(shí)(2023.03)采用的是當(dāng)前最新版本:

項(xiàng) 版本
react & react-dom ^18.2.0
react-router & react-router-dom ^6.11.2
antd ^4.24.8
@commitlint/cli & @commitlint/config-conventional ^17.4.4
eslint-config-prettier ^8.6.0
husky ^8.0.3
lint-staged ^13.1.2
prettier 2.8.4
json-server 0.17.2
craco-less ^2.0.0
@craco/craco ^7.1.0
qs ^6.11.0
dayjs ^1.11.7
react-helmet ^6.1.0
@types/react-helmet ^6.1.6
react-query ^6.1.0
@welldone-software/why-did-you-render ^7.0.1
@emotion/react & @emotion/styled ^11.10.6

具體配置、操作和內(nèi)容會(huì)有差異,“坑”也會(huì)有所不同。。。


一、項(xiàng)目起航:項(xiàng)目初始化與配置

  • 一、項(xiàng)目起航:項(xiàng)目初始化與配置

二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表

  • 二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表

三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類型

  • 三、 TS 應(yīng)用:JS神助攻 - 強(qiáng)類型

四、JWT、用戶認(rèn)證與異步請求

  • 四、 JWT、用戶認(rèn)證與異步請求(上)

  • 四、 JWT、用戶認(rèn)證與異步請求(下)

五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式

  • 五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式(上)

  • 五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式(下)

六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(上)

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(中)

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(下)

七、Hook,路由,與 URL 狀態(tài)管理

  • 七、Hook,路由,與 URL 狀態(tài)管理(上)

  • 七、Hook,路由,與 URL 狀態(tài)管理(中)

  • 七、Hook,路由,與 URL 狀態(tài)管理(下)

八、用戶選擇器與項(xiàng)目編輯功能

  • 八、用戶選擇器與項(xiàng)目編輯功能(上)

  • 八、用戶選擇器與項(xiàng)目編輯功能(下)

九、深入React 狀態(tài)管理與Redux機(jī)制

1&2

  • 九、深入React 狀態(tài)管理與Redux機(jī)制(一)

3&4

  • 九、深入React 狀態(tài)管理與Redux機(jī)制(二)

5~8

  • 九、深入React 狀態(tài)管理與Redux機(jī)制(三)

9&10

  • 九、深入React 狀態(tài)管理與Redux機(jī)制(四)

11.用redux-thunk管理登錄狀態(tài)

既然模態(tài)框使用 redux 來管理了,而 reduxcontext 是競爭關(guān)系,那可以嘗試將之前管理登錄狀態(tài)的 context 改為 redux

新建 src\store\auth.slice.ts

import { User } from "screens/ProjectList/components/SearchPanel";
import { createSlice } from "@reduxjs/toolkit";
import * as auth from 'auth-provider'
import { AuthForm, initUser as _initUser } from "context/auth-context";
import { AppDispatch, RootState } from "store";

interface State {
  user: User | null
}

const initialState: State = {
  user: null
}

export const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    setUser(state, action) {
      state.user = action.payload
    }
  }
})

const { setUser } = authSlice.actions

export const selectUser = (state: RootState) => state.auth.user

export const login = (form: AuthForm) => (dispatch: AppDispatch) => auth.login(form).then(user => dispatch(setUser(user)))
export const register = (form: AuthForm) => (dispatch: AppDispatch) => auth.register(form).then(user => dispatch(setUser(user)))
export const logout = () => (dispatch: AppDispatch) => auth.logout().then(() => dispatch(setUser(null)))
export const initUser = () => (dispatch: AppDispatch) => _initUser().then(user => dispatch(setUser(user)))

需要提前將 src\context\auth-context.tsx 中的 interface AuthForminitUser(視頻中對應(yīng)bootstrapUser) 導(dǎo)出

最后在 src\store\index.ts 中統(tǒng)一注冊:

...
import { authSlice } from "./auth.slice";

// 集中狀態(tài)注冊
export const rootReducer = {
  projectList: projectListSlice.reducer,
  auth: authSlice.reducer
};
...

接下來使用 redux 中的 auth 相關(guān)功能替換原有 context 提供的 auth 的功能

重構(gòu)需要找代碼上游中集中的一個(gè)點(diǎn):useAuth

修改 src\context\auth-context.tsx

+ import { ReactNode, useCallback } from "react";
...
+ import * as authStore from 'store/auth.slice'
+ import { useDispatch, useSelector } from "react-redux";
+ import { AppDispatch } from "store";

- interface AuthForm {
+ export interface AuthForm {
  username: string;
  password: string;
}

- const initUser = async () => {
+ export const initUser = async () => {
  let user = null;
  const token = auth.getToken();
  if (token) {
    // 由于要自定義 token ,這里使用 http 而非 useHttp
    const data = await http("me", { token });
    user = data.user;
  }
  return user
};

- const AuthContext = React.createContext<
-   | {
-       user: User | null;
-       login: (form: AuthForm) => Promise<void>;
-       register: (form: AuthForm) => Promise<void>;
-       logout: () => Promise<void>;
-     }
-   | undefined
- >(undefined);

- AuthContext.displayName = "AuthContext";

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  // 這里要考慮到初始值的類型與后續(xù)值類型,取并組成一個(gè)泛型
  const {
-     data: user,
    error,
    isLoading,
    isReady,
    isError,
    run,
-     setData: setUser,
  } = useAsync<User | null>();
+   // const dispatch: (...args: unknown[]) => Promise<User> = useDispatch()
+   // const dispatch: AppDispatch = useDispatch()
+ 
+   // 這種寫法雖然消除了代碼中的報(bào)錯(cuò),但是控制臺(tái)會(huì)有報(bào)錯(cuò)
+   // useMount(async () => run(dispatch(await initUser())));
+   // useMount(() => run(dispatch(initUser())));
+   // 還原后登錄保持功能已經(jīng)是不好使的了
  useMount(() => run(initUser()));
  
-   const login = (form: AuthForm) => auth.login(form).then(setUser);
-   const register = (form: AuthForm) => auth.register(form).then(setUser);
-   const logout = () => auth.logout().then(() => setUser(null));

  if (isReady || isLoading) {
    return <FullPageLoading />;
  }

  if (isError) {
    return <FullPageErrorFallback error={error} />;
  }

-   return (
-     <AuthContext.Provider
-       children={children}
-       value={{ user, login, register, logout }}
-     />
-   );
+   return <div>
+     { children }
+   </div>
};

export const useAuth = () => {
-   const context = React.useContext(AuthContext);
-   if (!context) {
-     throw new Error("useAuth 必須在 AuthProvider 中使用");
-   }
-   return context;
+   // 這種寫法有報(bào)錯(cuò)
+   // const dispatch: (...args: unknown[]) => Promise<User> = useDispatch()
+   const dispatch: AppDispatch = useDispatch()
+   const user = useSelector(authStore.selectUser)
+   const login = useCallback((form: AuthForm) => dispatch(authStore.login(form)), [dispatch])
+   const register = useCallback((form: AuthForm) => dispatch(authStore.register(form)), [dispatch])
+   const logout = useCallback(() => dispatch(authStore.logout()), [dispatch])
+   // const login = useCallback((form: AuthForm) => authStore.login(form), [])
+   // const register = useCallback((form: AuthForm) => authStore.register(form), [])
+   // const logout = useCallback(() => authStore.logout(), [])
+   // login({ username: '123', password: '123' }).then()
+   return { user, login, register, logout };
};

這種寫法會(huì)報(bào)錯(cuò) const dispatch: (...args: unknown[]) => Promise<User> = useDispatch()

不能將類型“Dispatch<AnyAction>”分配給類型“(...args: unknown[]) => Promise<User>”。
  參數(shù)“action”和“args” 的類型不兼容。
    不能將類型“unknown”分配給類型“AnyAction”

替換為 const dispatch: AppDispatch = useDispatch() 后正常

useMount(async () => run(dispatch(await initUser()))) 中不加 async..await 的話會(huì)有如下報(bào)錯(cuò)提示:

沒有與此調(diào)用匹配的重載。
  第 1 個(gè)重載(共 3 個(gè)),“(thunkAction: ThunkAction<Promise<User | null>, { projectList: State; auth: State; }, undefined, AnyAction>): Promise<User | null>”,出現(xiàn)以下錯(cuò)誤。
    類型“Promise<any>”的參數(shù)不能賦給類型“ThunkAction<Promise<User | null>, { projectList: State; auth: State; }, undefined, AnyAction>”的參數(shù)。
      類型“Promise<any>”提供的內(nèi)容與簽名“(dispatch: ThunkDispatch<{ projectList: State; auth: State; }, undefined, AnyAction>, getState: () => { projectList: State; auth: State; }, extraArgument: undefined): Promise<...>”不匹配。
  第 2 個(gè)重載(共 3 個(gè)),“(action: AnyAction): AnyAction”,出現(xiàn)以下錯(cuò)誤。
    類型“Promise<any>”的參數(shù)不能賦給類型“AnyAction”的參數(shù)。
      類型 "Promise<any>" 中缺少屬性 "type",但類型 "AnyAction" 中需要該屬性。
  第 3 個(gè)重載(共 3 個(gè)),“(action: AnyAction | ThunkAction<Promise<User | null>, { projectList: State; auth: State; }, undefined, AnyAction>): AnyAction | Promise<...>”,出現(xiàn)以下錯(cuò)誤。
    類型“Promise<any>”的參數(shù)不能賦給類型“AnyAction | ThunkAction<Promise<User | null>, { projectList: State; auth: State; }, undefined, AnyAction>”的參數(shù)。
      不能將類型“Promise<any>”分配給類型“AnyAction”。ts(2769)
auth-context.tsx(41, 31): 是否忘記使用 "await"?
index.d.ts(19, 3): 在此處聲明了 "type"。
auth-context.tsx(41, 31): 是否忘記使用 "await"?
auth-context.tsx(41, 31): 是否忘記使用 "await"?

最終運(yùn)行結(jié)果:登錄,注冊,登出功能都正常,只有登錄保持不正常


部分引用筆記還在草稿階段,敬請期待。。。文章來源地址http://www.zghlxwxcb.cn/news/detail-640763.html

到了這里,關(guān)于【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(五) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級(jí)項(xiàng)目(二十)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包