数据驱动视图 相当于 ==> ref reactive

获取DOM 元素 Ref


发布评论功能

发请求

监听 useEffect 函数 三个状态

hooks 注意事项

路由穿参


路由嵌套 二级路由

穿梭组件 穿梭到body
{createPortal(<GlobalAudioElement ref={audioRef} />, document.body)}
类中的构造期 是否需要添加super

类式组件

函数式组件 props 基础使用

生命周期


新的生命周期钩子

路由的严格匹配

强制刷新组件 forceUpdate

保存一个旧值

forwardRef 和 useImperativeHandle 相当于 vue中的defineExport

终止fetch请求 使用useEffect 清理函数 AbortController

TS typeof 自动获取类型 不用使用any了

useState useEffect useReducer
usestate 相当于vue的 ref
useReducer 相当于vue的 reactive
useEffect 相当于vue的 watch + cumputed + const
React.memo 缓存变化,只有props 发生变化才会重新渲染

useMemo函数的返回值是一个计算好的值,而不是函数

zustand 相当于 pinia
store / price.jsx
import { create } from 'zustand'
const usePriceStore = create((set) => ({
price: 0,
setPrice: (price) => set(() => ({ price })),
addPrice: (price) => set((state) => ({ price: state.price + price })),
}))
export default usePriceStore;
A 组件
import usePriceStore from '../../store/price';
const A = () => {
const { price, addPrice } = usePriceStore();
console.log('price ===>', price);
return (
<div>
<h1>A</h1>
<h2>{price}</h2>
<button onClick={() => addPrice(100)}>add</button>
</div>
);
};
export default A;
Zustand 中间件网址https://zustand.nodejs.cn/docs/middlewares/persist
Zustand + immer 案例 代码片段
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
const usePriceStore = create()(
immer((set) => ({
price: 0,
aaa: {
bbb: {
ccc: 0,
ddd: 2,
eee: 3
},
},
setPrice: (price) => set(() => ({ price })),
addPrice: (price) => set((state) => ({ price: state.price + price })),
setBbb: () => set((state) => { state.aaa.bbb.ccc = state.aaa.bbb.ccc + 1 }
),
}))
)
export default usePriceStore;
zustand useShallow,避免重复渲染问题
zustand redux devtools 调试中间件
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
+ import { devtools } from 'zustand/middleware'
const usePriceStore = create()(
immer(
+ devtools(
(set) => ({
price: 0,
aaa: {
bbb: {
ccc: 0,
ddd: 2,
eee: 3
},
},
setPrice: (price) => set(() => ({ price })),
addPrice: (price) => set((state) => ({ price: state.price + price })),
setBbb: () => set((state) => { state.aaa.bbb.ccc = state.aaa.bbb.ccc + 1 }
),
}),
+ { name: 'priceStore' }
)
+ )
)
export default usePriceStore;
Zustand 持久化存储
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
+ import { devtools, persist, createJSONStorage } from 'zustand/middleware'
const usePriceStore = create()(
immer(
+ persist(
devtools(
(set) => ({
price: 0,
aaa: {
bbb: {
ccc: 0,
ddd: 2,
eee: 3
},
},
setPrice: (price) => set(() => ({ price })),
addPrice: (price) => set((state) => ({ price: state.price + price })),
setBbb: () => set((state) => { state.aaa.bbb.ccc = state.aaa.bbb.ccc + 1 }
),
}),
{
name: 'priceStore',
}
),
+ {
+ name: 'priceStore',
+ storage: createJSONStorage(() => sessionStorage),
+ // partialize 用的不多 可以自定义存储
+ }
+ )
)
)
export default usePriceStore;
性能优化 独立监听某一个 避免hooks 持续调用
+import React, { useEffect, useRef } from 'react';
import A from '../A/index';
import B from '../B/index';
+import usePriceStore from '../../store/price';
function HelloWorld(props) {
+ useEffect(() => {
+ usePriceStore.subscribe((state) => state.price, (price, prevPrice) => {
+ console.log('price change ===>', price, prevPrice);
+ })
+ return () => {
+ usePriceStore.unsubscribe()
+ }, {
+ fireImmediately: true,
+ equalityFn: (a, b) => a === b,
+ }
+ }, []);
return (
<div>
<A />
<hr />
<B />
</div>
);
}
export default HelloWorld;
tailwind 封装到独立的文件中

将 useSearchParams 转换为对象, 并附上类型
'use client'
import { useSearchParams } from 'next/navigation'
import { useMemo } from 'react'
/**
* 将 useSearchParams 转换为对象, 并附上类型
* @example
* const searchParams = useSearchParamsObject<{ mode: string }>()
* const mode = searchParams.mode
* mode 的类型为 string | undefined
*/
export function useSearchParamsObject<T>() {
const searchParams = useSearchParams()
const searchParamsObject = useMemo(() => {
return Object.fromEntries(searchParams.entries()) as Partial<T>
}, [searchParams])
return searchParamsObject
}
Mobx-react 函数式组件


MobX 类组件

