单例状态容器 (Singleton Store)
概述
单例状态容器是最简单的全局状态管理方案,使用单一对象存储应用状态,并提供订阅机制监听状态变化。
特点
- ✅ 实现简单,零学习成本
- ✅ 全局单例,任意位置访问
- ✅ 支持状态快照和批量更新
- ✅ 回调可获取前一个值
- ⚠️ 无中间件机制
- ⚠️ 无时间旅行调试
核心类
Store<T>
interface AppState {
user: User
theme: 'light' | 'dark'
cart: CartItem[]
}
const store = new Store<AppState>()
// 设置状态
store.setState('user', { id: 1, name: 'John' })
// 获取状态
const user = store.getState('user')
// 订阅(返回取消订阅函数)
const unsubscribe = store.subscribe('user', (newUser, prevUser) => {
console.log('User changed from', prevUser, 'to', newUser)
})
// 取消订阅
unsubscribe()
// 批量更新
store.batchUpdate({
theme: 'dark',
cart: []
})
// 获取快照
const snapshot = store.getSnapshot()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
API 文档
推荐用法(Store 风格)
import {
setState,
getState,
deleteState,
subscribe,
getSnapshot,
batchUpdate,
resetStore
} from './StoreSingleton'
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
setState(key, value)
设置状态,通知订阅者。
setState('user.settings', { language: 'zh-CN' })
1
getState(key)
获取状态值。
const settings = getState<UserSettings>('user.settings')
1
subscribe(key, callback)
订阅状态变化。如果已有值,立即触发回调。
const unsubscribe = subscribe('user.settings', (settings) => {
applySettings(settings)
})
// 取消订阅
unsubscribe()
1
2
3
4
5
6
2
3
4
5
6
deleteState(key)
删除状态并通知订阅者。
deleteState('user.settings')
1
getSnapshot()
获取所有状态的快照。
const allState = getSnapshot()
console.log(allState)
// { 'user.settings': {...}, 'cart.items': [...] }
1
2
3
2
3
batchUpdate(updates)
批量更新多个状态。
batchUpdate({
'user.profile': { name: 'John' },
'user.settings': { theme: 'dark' }
})
1
2
3
4
2
3
4
resetStore()
重置所有状态(会触发所有订阅者)。
resetStore()
1
React Hook 示例
function useStore<T>(key: string): [T | undefined, (value: T) => void] {
const [value, setValue] = useState<T | undefined>(() => getState<T>(key))
useEffect(() => {
return subscribe<T>(key, (next) => setValue(next))
}, [key])
const setStoreValue = useCallback(
(newValue: T) => {
setState(key, newValue)
},
[key]
)
return [value, setStoreValue]
}
// 使用
function ThemeToggle() {
const [theme, setTheme] = useStore<'light' | 'dark'>('app.theme')
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
当前主题: {theme}
</button>
)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
带前值的订阅
Store 的订阅回调可以获取前一个值:
import { store } from './StoreSingleton'
store.subscribe('counter', (newValue, prevValue) => {
console.log(`Counter changed from ${prevValue} to ${newValue}`)
})
1
2
3
4
5
2
3
4
5
类型安全用法
使用 createStore 创建类型安全的 Store:
import { createStore } from './Store'
interface MyAppState {
user: User | null
products: Product[]
cart: { items: CartItem[]; total: number }
}
const appStore = createStore<MyAppState>()
// 类型安全
appStore.setState('user', { id: 1, name: 'John' }) // ✅
appStore.setState('user', 'invalid') // ❌ 类型错误
const user = appStore.getState('user') // 类型: User | null | undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
适用场景
- 小型应用的全局状态管理
- 需要简单状态共享的场景
- 不想引入 Redux/Zustand 等库
- 需要状态快照功能
