引言
最近公司需求较少,去B站跟着一位学习了一下,主要是对一些代码加了自己理解的注释,有需要的直接看注释吧
store.js
import { create } from 'zustand'
import { createJSONStorage, devtools, persist, subscribeWithSelector } from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'
devtools
interface AppleStore {
price: number
count: number
color: string
addCount: () => void
decrement: () => void
getTotal: () => number
doubleCount: () => Promise<undefined>
}
const useAppleStore = create<AppleStore>()(
// 同步修改中间件
immer(
// 使用redux调试
devtools(
// 订阅细化中间件
subscribeWithSelector(
// 持久化存储中间件
persist(
// 状态回调
(set, get) => ({
price: 10,
count: 5,
color: 'red',
// 增加数量
addCount: () => {
set((state) => {
state.count += 1
})
},
// 常规修改
// addCount:()=>{
// set((state)=>({count: state.count + 1}))
// },
// 减少数量
decrement: () => {
set((state) => {
state.count -= 1
})
},
getTotal: () => {
return get().price * get().count
},
async doubleCount() {
const rate = await Promise.resolve(2)
set((state) => {
state.count *= rate
})
},
}),
{
name: 'myAppleStore',
// 持久化选择一条数据
// partialize:(state) => ({price:state.price})
// 持久化筛出某一条price
// Object.fromEntries -- 二维数组转对象 [[aa:'bb']] => {aa:'bb'}
// Object.entries -- 对象转二维数组 {aa:'bb'} => [[aa:'bb']]
partialize: (state) => Object.fromEntries(Object.entries(state).filter(([key]) => !['price'].includes(key))),
// 存入sessionStorage还是localStorage
storage: createJSONStorage(() => sessionStorage),
}
)
),
{ enabled: true, name: 'apple Store' }
)
)
)
export default useAppleStore
// 单独封装store修改方法 --- 原作者推荐
export const addCount = () => {
useAppleStore.setState((state) => {
state.count += 1
})
}
export const decrement = () => {
useAppleStore.setState((state) => {
state.count -= 1
})
}
export const getTotal = () => {
return useAppleStore.getState().price * useAppleStore.getState().count
}
export const doubleCount = async () => {
const rate = await Promise.resolve(2)
useAppleStore.setState((state) => {
state.count *= rate
})
}
App.tsx
import { Fragment, useEffect, useState } from 'react'
import './App.css'
import useAppleStore, { addCount, decrement, doubleCount, getTotal } from './store/appleStore'
import { useShallow } from 'zustand/react/shallow'
import { shallow } from 'zustand/shallow'
const Child1 = () => {
// 取值方法1
const price = useAppleStore((state) => state.price)
const count = useAppleStore((state) => state.count)
// const addCount = useAppleStore((state) => state.addCount)
// const decrement = useAppleStore((state) => state.decrement)
// const getTotal = useAppleStore((state) => state.getTotal)
// const doubleCount = useAppleStore((state) => state.doubleCount)
/**
* 组件修改store状态
*/
const myLocalAction = () => {
// 修改数据
useAppleStore.setState((state) => ({
...state,
price: state.price + 10
}))
// 拿取数据
console.log(useAppleStore.getState().price)
}
return (
<Fragment>
<h1>价格:{price}</h1>
<h1>数量:{count}</h1>
<h1>总量:{getTotal()}</h1>
<button onClick={addCount}>+1</button>
<button onClick={decrement}>-1</button>
<button onClick={doubleCount}>* 2 </button>
<button onClick={myLocalAction}>独有状态+10</button>
</Fragment>
)
}
const Child2 = () => {
const [text, setText] = useState('太少')
// 取值方法2 -- 推荐
const {color, price} = useAppleStore(useShallow(state => ({
color: state.color,
price: state.price,
})))
useEffect(() => {
// 订阅,减少组件重新渲染 -- 监听所有state
// const cancelSub = useAppleStore.subscribe((state, prevState) => {
// if(state.count >= 7 && prevState.count < 7){
// console.log(state.count)
// setText('太多了')
// } else if(state.count < 7 && prevState.count >= 7){
// setText('太少')
// }
// })
// 单一监听state中的count,需要搭配subscribeWithSelector
const cancelSub = useAppleStore.subscribe(state => state.count, (count, prevCount) => {
console.log(count)
if(count >= 7 && (prevCount < 7 || count === prevCount)){
setText('太多了')
} else if(count < 7 && (prevCount >= 7 || count === prevCount)){
setText('太少')
}
},
{
equalityFn: shallow,
// 首次立即执行
fireImmediately:true
},
)
return cancelSub
}, [])
console.log('child2 ---- ')
return (
<>
<h1>价格:{price}</h1>
<h1>颜色:{color}</h1>
<h1>{text}</h1>
</>
)
}
function App() {
const [count, setCount] = useState(0)
return (
<>
<Child1/>
<Child2/>
</>
)
}
export default App