db-hooks
是一款小巧的范式化State管理工具(推荐使用normalizr范式化数据),完美解决的本地数据不同步的问题。如果你厌烦了不停处理项目中各种数据同步问题,那么不妨来试试db-hooks
能完美满足你的需求。
常见数据不同步场景如下
// PageA (article list)
data: [{article1}, {article2}, {article3}...]
// 点击article2进入 article2详情页面 PageB(artice2 detail)
data: {article2}
这时候在pageB对article2进行点赞(点赞数+1)等副作用操作只会影响当前PageB里的article数据
返回PageA article2显示的点赞数及点赞状态都与PageB中的不一致,产生这种现象的原因就是同一个article数据存在了多份,副作用操作只能影响到当前page的article。
解决这种问题的思路就是将所有视为统一类型的数据仅保留一份。实现方式如下:
- 本地维护一个对象充当数据库
- 页面获取数据后不直接持有数据,而是拿着数据去更新数据库,然后仅保留id,用id去数据库查找数据。
- 不同组件编辑数据会直接修改数据库中的数据,所有引用该数据的组件都会触发更新。
- 使用hooks实现,零依赖,零学习成本。
- 结构简单,核心代码不足100行。
- 完整的Typescript支持
npm i db-hooks --save
// 服务器返回的json
[
{
id: 42,
title: '宇宙终极答案',
like: false,
likeNum: 233,
user: {
id: 22,
nickname: '22娘'
}
},
{
id: 89757,
title: '编号:89757',
like: true,
likeNum: 9,
user: {
id: 33,
nickname: '33娘'
}
}
]
// 类型声明
type SchemaID = number // SchemaID表示 表关系
export interface Article {
id: number
title: string
user: SchemaID
like: boolean
likeNum: number
}
export interface User {
id: number
nickname: string
}
// 创建schema
export const user = new schema.Entity('user')
export const article = new schema.Entity('article', {
user
})
// 初始化数据库
import {createDB} from 'db-hooks'
export const {useDB, updateDB, editDB} = createDB<{
article: Article,
user: User
}>({
article: {},
user: {}
}, {
article: {},
user: {}
})
const [ids, setIds] = useState([])
fetchData().then(res=>{ // 服务器返回的json
const data = normalize(res, [article]) // normalizr范式化数据
updateDB(data.entities) // 会对db进行merge操作
setIds(data.result)
})
const Cell: React.FC<{id: number}> = ({id}) => {
const article = useDB('article', id)
const user = useDB('user', article.user)
const onLikeClick = useCallback((event: ITouchEvent)=>{
event.stopPropagation()
editDB(db=>{
db.article[id].likeNum = article.like? article.likeNum - 1: article.likeNum + 1,
db.article[id].like = !article.like
})
}, [article])
return <View className='article-cell' style={{fontSize: '20px', color:'#666666', marginBottom: '20px'}}>
<View>发布者: {user.nickname}</View>
<View>{article.title}</View>
<View>
<Text onClick={onLikeClick} style={{color: article.like? 'red' : ''}}>{article.like? '已赞' : '点赞'}: </Text>
<Text>{article.likeNum}</Text>
</View>
</View>
}
<View>
{ids.map(id=><Cell id={id} />)}
</View>
snapshotDB
// 可以使用snapshotDB查看数据库快照,可以在非顶层函数中使用.
for(let id of articleIds){
cosnt article = snapshotDB('article', id)
}
cd example
npm i
npm run dev:h5