shared/ui/hooks/useDirtyTracker.ts

47 lines
1.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useState, useRef } from 'react'
/**
* 脏状态追踪 Hook — 用于"修改后才显示保存按钮"模式。
*
* @example 数组场景(每个子项独立保存)
* const { isDirty, markClean, removeItem } = useDirtyTracker()
* {items.map(item => (
* <div key={item.id}>
* <input onChange={...} />
* {isDirty(item.id, item) && <button onClick={save}>保存</button>}
* </div>
* ))}
* // 保存成功后: markClean(id, savedItem)
* // 删除时: removeItem(id)
*/
export function useDirtyTracker() {
const savedMap = useRef<Map<string, string>>(new Map())
/**
* 判断指定 key 的当前数据是否相对于上次 markClean 有修改。
* 从未 markClean 过的 key 视为 dirty适用于新增项
*/
const isDirty = (key: string, current: unknown): boolean => {
const saved = savedMap.current.get(key)
if (saved === undefined) return true // 从未保存过 → dirty
return saved !== JSON.stringify(current)
}
/**
* 将指定 key 的当前数据标记为"已保存"(重置 dirty 状态)。
*/
const markClean = (key: string, item: unknown): void => {
savedMap.current.set(key, JSON.stringify(item))
}
/**
* 删除指定 key 的追踪记录(用于列表项被删除时清理)。
*/
const removeItem = (key: string): void => {
savedMap.current.delete(key)
}
return { isDirty, markClean, removeItem }
}