V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Outshine
V2EX  ›  Next.js

关于 next.js 13 请求封装的最佳实践的疑问

  •  
  •   Outshine · 2023-04-10 02:16:29 +08:00 · 4449 次点击
    这是一个创建于 591 天前的主题,其中的信息可能已经有所发展或是发生改变。
    首先声明,本人之前一直做的都是 SPA 项目,直接用 `axios` 之类的封装一次即可,而我说的封装是指类似做 baseUrl 、统一错误处理、统一设置请求 headers 等

    ---

    我看 next.js 13 官方建议 `Server Component` 使用 `fetch`,`Client Component` 请求数据使用 `swr` 或者 `react query`

    而 `swr` 官方文档和网上文章没有关于 `swr` 提交数据相关的(看起来就是专门获取数据的库?)

    那么,服务端组件请求、客户端组件请求、客户端提交数据是要封装三次嘛?想问下各位 next.js 前辈有什么好一点的实践嘛?
    8 条回复    2023-04-10 19:26:25 +08:00
    seki
        1
    seki  
       2023-04-10 02:34:23 +08:00
    swr 有的,叫做 mutation ,按關鍵字找一下

    server 和 client 運行的環境本來不一樣,分別封裝一下比較合理。client 的話,swr 可以全局配置 fetcher 和 mutator ,取決於你的項目實際,也可以抽象 get / post 方法再封裝
    himself65
        2
    himself65  
       2023-04-10 02:38:21 +08:00 via iPhone   ❤️ 2
    swr 是一个网络无关的异步数据获取库,你可以拿来跑任何异步函数。
    在你说的这个例子里面,你可以在顶层写一个 fetcher(key),包装了 fetch api ,然后三个部分都可以间接 /直接调用这个 API
    shuding
        3
    shuding  
       2023-04-10 05:21:05 +08:00   ❤️ 1
    `useSWRMutation` 这个 hook 可以用来处理 POST/PUT/DELETE 之类的请求:

    https://swr.vercel.app/docs/mutation#useswrmutation
    B3C933r4qRb1HyrL
        4
    B3C933r4qRb1HyrL  
       2023-04-10 08:35:47 +08:00 via Android
    握草,上面两位大佬亲自回复
    wu67
        5
    wu67  
       2023-04-10 08:44:59 +08:00
    最近也在看, 我也是搞不懂, getServerSideProps 里面貌似只有 fetch, 这玩意根本没有文档, 怎么发 post 请求都不明白...

    还是说 swr 也能在服务端代码运行的?

    还有 swr 如果在不停的刷新新数据, 那不是一直在调 API 读数据库? 用户量上来之后这不是平白增加数据库压力嘛?
    iliaoliao
        6
    iliaoliao  
       2023-04-10 11:30:30 +08:00
    首先你需要明白哪些请求是幂等的,增删改查中查是幂等的所以使用 `useQuery` 这类带有数据缓存的 hook 是最合适的,而增删改等非幂等操作则使用带有突变操作的 hook `useMutation`。
    我推荐 react-query 和我开源的 react-query-kit 结合使用。可以做到在 getServerSideProps 和组件中的写法是一致的,几乎没有什么心智负担,顺便把写法贴在下面

    ```js
    import { createQuery } from 'react-query-kit'

    const usePost = createQuery({
    primaryKey: '/posts',
    queryFn: ({ queryKey: [primaryKey, variables] }) => {
    // primaryKey equals to '/posts'
    return fetch(`${primaryKey}/${variables.id}`).then(res => res.json())
    },
    })

    const variables = { id: 1 }

    export default function Page() {
    const { data } = usePost({ variables, suspense: true })

    return (
    <div>
    <div>{data?.title}</div>
    <div>{data?.content}</div>
    </div>
    )
    }

    // nextjs example
    export async function getStaticProps() {
    const queryClient = new QueryClient()

    await queryClient.prefetchQuery({
    queryKey: usePost.getKey(variables),
    queryFn: usePost.queryFn
    })

    return {
    props: {
    dehydratedState: dehydrate(queryClient),
    },
    }
    }
    ```
    Outshine
        7
    Outshine  
    OP
       2023-04-10 17:56:52 +08:00
    感谢各位大佬的解答

    @himself65 #2 因为 next.js 13 规定客户端组件必须在文件头增加 'use client' ,而且 swr 使用了客户端组件才能用的一些 hooks ,所以服务端组件和客户端组件貌似还是需要单独封装

    @shuding #3 瞅了瞅这个文档,文档里的 demo 是将 token 手动传入,貌似不够优雅。但如果统一封装,又会遇到上面的问题(因为服务端和客户端获取 token 的途径肯定不一样的,我尝试过通过判断是否服务端来从不同路径获取,但是 next.js 13 不允许服务端组件里存在客户端的代码,连导入都不行)

    @wu67 #5 fetch 发 post 请求倒是很简单,直接 fetch('url', { method: 'POST' } 即可。swr 在 next.js 13 上并不能在服务端运行(我没试过之前的版本)

    @iliaoliao #6 感谢,您这个看起来也不支持 next.js 13 呢?而且我按照您 github 的文档并没有顺利跑起来。
    iliaoliao
        8
    iliaoliao  
       2023-04-10 19:26:25 +08:00
    @Outshine
    GitHub 文档上都有示例项目的,例如这个 nextjs13 的 https://codesandbox.io/s/example-react-query-kit-nextjs-uldl88
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3022 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:03 · PVG 21:03 · LAX 05:03 · JFK 08:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.