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

2023-04-10 02:16:29 +08:00
 Outshine
首先声明,本人之前一直做的都是 SPA 项目,直接用 `axios` 之类的封装一次即可,而我说的封装是指类似做 baseUrl 、统一错误处理、统一设置请求 headers 等

---

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

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

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

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

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

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

还有 swr 如果在不停的刷新新数据, 那不是一直在调 API 读数据库? 用户量上来之后这不是平白增加数据库压力嘛?
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
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
2023-04-10 19:26:25 +08:00
@Outshine
GitHub 文档上都有示例项目的,例如这个 nextjs13 的 https://codesandbox.io/s/example-react-query-kit-nextjs-uldl88

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/931092

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX