You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅用Jotai实现分页加载数据的累加状态管理

解决方案:用Jotai原子替代useState/useEffect管理分页累积数据

核心思路

把分页数据的累积逻辑完全迁移到Jotai原子体系中:

  1. 新增原子存储所有已加载的漫画数据
  2. 利用Jotai的依赖追踪特性,当新分页数据加载完成时自动追加到全局数据原子
  3. 组件直接读取全局数据原子,移除useState和useEffect

代码实现

1. 定义核心原子

import { atom } from 'jotai'
import { loadable, atomWithEffect } from 'jotai/utils'

// 你的分页原子(假设已存在)
export const pagination = atom(1)

// 存储所有已加载的漫画数据
export const allComicsAtom = atom<Comics[]>([])

// 异步加载指定页的漫画数据
export const fetchComicsByPageAtom = atom(async (get) => {
  const page = get(pagination)
  const res = await getMarvelData({ resource: 'comics', page })
  return res.data.results as Comics[]
})

// 包装为可追踪加载状态的原子
export const loadableComics = loadable(fetchComicsByPageAtom)

// 副作用原子:新数据加载完成后自动追加到全局列表
export const appendComicsEffectAtom = atomWithEffect((get, set) => {
  const loadableState = get(loadableComics)
  if (loadableState.state === 'hasData') {
    set(allComicsAtom, prev => [...prev, ...loadableState.data])
  }
})

2. 简化组件代码

export function Main(): JSX.Element {
  // 订阅全局漫画数据和加载状态
  const [allComics] = useAtom(allComicsAtom)
  const [loadableState] = useAtom(loadableComics)
  // 订阅副作用原子(触发数据追加逻辑)
  useAtom(appendComicsEffectAtom)

  useEndOfPageObserver() // 原滚动加载逻辑,负责更新pagination的page值

  // 错误处理
  if (loadableState.state === 'hasError') return <Error />

  return (
    <main className='grid gap-4 grid-cols-4'>
      {allComics.map((comic) => (
        <ComicsCard comics={comic} key={comic.id} />
      ))}
      {/* 加载状态提示 */}
      {loadableState.state === 'loading' && <Loading />}
    </main>
  )
}

关键说明

  • allComicsAtom:作为单一数据源,存储所有已加载的漫画数据,替代原来的useState
  • atomWithEffect:监听loadableComics的状态变化,当新数据加载完成时自动追加到全局列表,替代原来的useEffect
  • 组件只需要读取原子状态,不再需要手动处理数据累积逻辑,完全由Jotai的依赖驱动更新

内容的提问来源于stack exchange,提问作者dev.iamunhoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:37:52