刷网站排名 优帮云,体育网站模版,网站建设,h5,小程序,求个没封的网站2022文章目录 一、项目起航#xff1a;项目初始化与配置二、React 与 Hook 应用#xff1a;实现项目列表三、TS 应用#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook… 文章目录 一、项目起航项目初始化与配置二、React 与 Hook 应用实现项目列表三、TS 应用JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook路由与 URL 状态管理八、用户选择器与项目编辑功能九、深入React 状态管理与Redux机制123.合并组件状态实现useUndo4.用useReducer进行状态管理 学习内容来源React React Hook TS 最佳实践-慕课网 相对原教程我在学习开始时2023.03采用的是当前最新版本
项版本react react-dom^18.2.0react-router react-router-dom^6.11.2antd^4.24.8commitlint/cli commitlint/config-conventional^17.4.4eslint-config-prettier^8.6.0husky^8.0.3lint-staged^13.1.2prettier2.8.4json-server0.17.2craco-less^2.0.0craco/craco^7.1.0qs^6.11.0dayjs^1.11.7react-helmet^6.1.0types/react-helmet^6.1.6react-query^6.1.0welldone-software/why-did-you-render^7.0.1emotion/react emotion/styled^11.10.6
具体配置、操作和内容会有差异“坑”也会有所不同。。。 一、项目起航项目初始化与配置 一、项目起航项目初始化与配置 二、React 与 Hook 应用实现项目列表 二、React 与 Hook 应用实现项目列表 三、TS 应用JS神助攻 - 强类型 三、 TS 应用JS神助攻 - 强类型 四、JWT、用户认证与异步请求 四、 JWT、用户认证与异步请求(上) 四、 JWT、用户认证与异步请求(下) 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(上) 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) 六、用户体验优化 - 加载中和错误状态处理 六、用户体验优化 - 加载中和错误状态处理(上) 六、用户体验优化 - 加载中和错误状态处理(中) 六、用户体验优化 - 加载中和错误状态处理(下) 七、Hook路由与 URL 状态管理 七、Hook路由与 URL 状态管理(上) 七、Hook路由与 URL 状态管理(中) 七、Hook路由与 URL 状态管理(下) 八、用户选择器与项目编辑功能 八、用户选择器与项目编辑功能(上) 八、用户选择器与项目编辑功能(下) 九、深入React 状态管理与Redux机制
12 九、深入React 状态管理与Redux机制(一) 3.合并组件状态实现useUndo
功能描述
可以对一个数字进行不断地赋值同时记录下历史值可以通过undo对当前值进行撤销操作一步步地回到最初值。在进行撤销操作的同时记录下undo掉的值通过redo可以回到undo之前的值不断地redo最终可以回到执行所有撤销操作之前的值。
代码实现
使用useState实现该hook由于多个state值之前相互引用。因此useCallback的依赖项中会填入多个state作为依赖项但是在useCallback的回调函数中在调用时会更新state值导致页面重新渲染useCallback的回调函数也被重新定义了。
接下来模仿实现 use-undo
use-undo-demo - CodeSandboxuse-undo - npm
新建 src\utils\use-undo.ts
import { useState } from react;export const useUndo T(initialPresent: T) {// 记录历史操作的合集const [past, setPast] useStateT[]([])const [present, setPresent] useState(initialPresent)// 记录未来操作的合集const [future, setFuture] useStateT[]([])const canUndo past.length ! 0const canRedo future.length ! 0const undo () {if (!canUndo) returnconst previous past[past.length - 1]const newPast past.slice(0, past.length - 1)setPast(newPast)setPresent(previous)setFuture([present, ...future])}const redo () {if (!canRedo) returnconst next future[0]const newFuture future.slice(1)setFuture(newFuture)setPresent(next)setPast([...past, present])}const set (newPresent: T) {if (newPresent present) {return}setPast([...past, present])setPresent(newPresent)setFuture([])}const reset (newPresent: T) {setPast([])setPresent(newPresent)setFuture([])}return [{past, present, future},{redo, undo, set, reset, canRedo, canUndo}] as const
}现需要对代码做以下优化
使用 useCallback 避免 造成之前的那种 依赖不等导致的循环渲染将用到的 变量合并声明 后续也同步改动SetXXX 使用函数形式 直接使用历史状态 避免外界状态的使用减少依赖
import { useCallback, useState } from react;export const useUndo T(initialPresent: T) {// 合并声明const [state, setState] useState{past: T[],present: T,future: T[]}({past: [],present: initialPresent,future: []})// 另一种写法// const [state, setState] useState({// past: [] as T[],// present: initialPresent as T,// future: [] as T[]// })const canUndo state.past.length ! 0const canRedo state.future.length ! 0const undo useCallback(() {setState(currentState {const { past, present, future } currentStateif (past.length 0) return currentStateconst previous past[past.length - 1]const newPast past.slice(0, past.length - 1)return {past: newPast,present: previous,future: [present, ...future]}})}, [])const redo useCallback(() {setState(currentState {const { past, present, future } currentStateif (future.length 0) return currentStateconst next future[0]const newFuture future.slice(1)return {past: [...past, present],present: next,future: newFuture}})}, [])const set useCallback((newPresent: T) {setState(currentState {const { past, present } currentStateif (newPresent present) {return currentState}return {past: [...past, present],present: newPresent,future: []}})}, [])const reset useCallback((newPresent: T) {setState({past: [],present: newPresent,future: []})}, [])return [state,{redo, undo, set, reset, canRedo, canUndo}] as const
}4.用useReducer进行状态管理
替代方案:
useReducer作为useState 的替代方案。它接收一个形如 (state, action) newState的 reducer并返回当前的 state 以及与其配套的 dispatch 方法。
相比较于useStateuseReducer 具有如下优点
state中的状态值之间相互关联下一个 state的更新依赖于之前的 state。 useReducer | Hook API 索引 – React 下面使用 useReducer 再对 use-undo 进行改写
编辑 src\utils\use-undo.ts
import { useCallback, useReducer, useState } from react;const UNDO UNDO
const REDO REDO
const SET SET
const RESET RESETtype StateT {past: T[];present: T;future: T[];
}type ActionT { newPresent?: T, type: typeof UNDO | typeof REDO | typeof SET | typeof RESET }const undoReducer T(state: StateT, action: ActionT) {const { past, present, future } stateconst { newPresent, type } actionswitch(type) {case UNDO: {if (past.length 0) return state;const previous past[past.length - 1];const newPast past.slice(0, past.length - 1);return {past: newPast,present: previous,future: [present, ...future],};}case REDO: {if (future.length 0) return state;const next future[0];const newFuture future.slice(1);return {past: [...past, present],present: next,future: newFuture,};}case SET: {if (newPresent present) {return state;}return {past: [...past, present],present: newPresent,future: [],};}case RESET: {return {past: [],present: newPresent,future: [],}}default: return state}
}export const useUndo T(initialPresent: T) {const [state, dispatch] useReducer(undoReducer, {past: [],present: initialPresent,future: [],} as StateT)const canUndo state.past.length ! 0;const canRedo state.future.length ! 0;const undo useCallback(() dispatch({ type: UNDO }), []);const redo useCallback(() dispatch({ type: REDO }), []);const set useCallback((newPresent: T) dispatch({newPresent, type: SET}), []);const reset useCallback((newPresent: T) dispatch({newPresent, type: RESET}), []);return [state, { redo, undo, set, reset, canRedo, canUndo }] as const;
};统一状态管理后 虽然代码量多了但是经过多重封装层次更加清晰
可以发现 useReducer 相对 useState 适合定义多个相互影响的状态量
鉴于 useReducer 针对复杂的state关系和更新的前后依赖的优势因此 useAsync 非常适合使用 useReducer 来重构
接下来使用 useReducer 改造一下 与 use-undo 结构类似的 use-async(src\utils\use-async.ts)
...
const useSafeDispatch T(dispatch: (...args: T[]) void) {const mountedRef useMountedRef()return useCallback((...args: T[]) (mountedRef.current ? dispatch(...args) : void 0), [dispatch, mountedRef])
}export const useAsync D(...) {const config { ...defaultConfig, ...initialConfig };const [state, dispatch] useReducer((state: StateD, action: PartialStateD) ({...state, ...action}), {...defaultInitialState,...initialState,});const safeDispatch useSafeDispatch(dispatch);const [rerun, setRerun] useState(() () {});const setData useCallback((data: D) safeDispatch(...),[safeDispatch]);const setError useCallback((error: Error) safeDispatch(...),[safeDispatch]);// run 来触发异步请求const run useCallback((...) {...safeDispatch({ stat: loading });return promise.then((data) {setData(data);return data;}).catch(...);},[config.throwOnError, safeDispatch, setData, setError]);...
};部分引用笔记还在草稿阶段敬请期待。。。