Zustand切片中使用subscribeWithSelector报错及订阅实现方案
Zustand中subscribeWithSelector的TypeScript错误解决与bears状态订阅实现
一、报错原因与store: StoreApi<...>参数说明
你碰到的TS错误是因为createBearSlice作为StateCreator类型函数,实际需要接收三个参数:set、get、store,但你调用时只传了前两个,导致参数不匹配。
这里的store: StoreApi<BearSlice>是Zustand提供的底层Store API实例,核心作用是暴露Store的底层操作能力:
subscribe: 用于订阅状态变更getState: 获取当前最新状态(和上层get功能类似,但属于底层API)setState: 直接修改状态(和上层set功能类似)
这个参数主要用于需要直接和Store实例交互的场景,比如添加全局订阅、配合中间件传递上下文。
二、正确实现bears状态订阅的两种方案
你的项目采用切片组合成全局Store的设计,不需要单独创建useBearStore,应该在全局Store上应用subscribeWithSelector中间件,再通过全局Store实现订阅。
1. 第一步:给全局Store添加subscribeWithSelector中间件
修改store/index.ts,引入并应用中间件:
import { create } from 'zustand' import { subscribeWithSelector } from 'zustand/middleware' import { createProjSlice, ProjSlice } from './proj.store' import { BearSlice, createBearSlice } from './bear.store' type StoreState = ProjSlice & BearSlice export const useStore = create<StoreState>()( subscribeWithSelector((...params) => ({ ...createProjSlice(...params), ...createBearSlice(...params) })) )
2. 方案一:在组件中订阅bears变化
在需要监听的组件内,使用useStore.subscribe实现订阅:
import { useEffect } from 'react' import { useStore } from './store' function BearComponent() { useEffect(() => { // 订阅bears状态,变化时执行自定义操作 const unsubscribe = useStore.subscribe( (state) => state.bears, // 指定要监听的状态字段 (newBears, oldBears) => { console.log('bears更新:', newBears, oldBears) // 这里写你的额外业务逻辑 } ) // 组件卸载时取消订阅,避免内存泄漏 return unsubscribe }, []) return <div>Bear Component</div> }
3. 方案二:在BearSlice内部自动订阅
如果希望Store初始化时就自动监听bears变化,可以在createBearSlice中利用第三个store参数:
import { StateCreator, StoreApi } from "zustand"; export interface BearSlice { bears: string[], addBear: () => void } export const createBearSlice: StateCreator<BearSlice> = (set, get, store) => { // 初始化时订阅bears变更 const unsubscribe = store.subscribe( (state) => state.bears, (newBears) => { console.log('bears内部监听触发:', newBears) // 执行你的额外操作 } ) // 可选:如果需要在Store销毁时清理订阅,可结合相关钩子处理 return { bears: [], addBear: () => { const { bears } = get() // 注意:必须遵循Immutable原则,不能直接修改原数组 const newBears = [...bears, '1'] set({ bears: newBears }) } } }
注意:原代码中直接修改
bears原数组的写法错误,违反Zustand的Immutable状态更新原则,会导致状态变更无法被正确监听,必须创建新数组更新状态。
三、清理错误代码
删除bear.store.ts中单独创建useBearStore的代码,改用上述全局Store方案即可解决原TS错误。
内容的提问来源于stack exchange,提问作者lme
相关产品推荐
相关产品推荐

