使用 server components 的前提下完全使用 url params 作为状态管理是否可行

2023-10-28 08:27:35 +08:00
 rocmax

由于 server components 的渲染早于 client components ,而且无法访问 context ,所以需要在两者之间共享 state 尤其是将客户端的变更反映到服务器端组件的时候,我现在想到的方法就是修改 url query params 然后跳转到这个新 url 。 网上也有一些提倡这样做的文章和视频,比如: https://youtu.be/ukpgxEemXsk?si=Dd9vJVfA4HBU0do3 https://dev.to/jeffsalive/solving-the-challenge-of-state-persistence-in-nextjs-effortless-state-management-with-query-parameters-4a6p

感觉大体上这种做法是可行的,但我如果客户端的状态比较复杂的话会不会带来问题?

1588 次点击
所在节点   Next.js
13 条回复
BugCry
2023-10-28 11:23:13 +08:00
1 ,URL 的长度有限制
2 ,如果 state 被恶意修改,阁下将如何应对?
hugepizza
2023-10-28 11:53:33 +08:00
cache revalidate 也是个问题 官方文档上的 revalidatePath 没有写是否支持 searchParams
至于 revalidateTag 我到现在也没搞懂这是个啥 🤣
rocmax
2023-10-28 11:56:23 +08:00
@BugCry 1 确实是一个硬性的限制,浏览器限制在 2048 字符以下,一般而言是够的,如果把使用 url 存储 state 作为一个原则的话可能会遇到极端情况无法处理。长 url 还会带来难以记录和共享的问题,优势是能将 app 恢复到特定状态。
第 2 点风险在哪里?客户端 state 本来就存在客户端,不管存在 context ,localstorage 还是 cookie 里,客户都是随便改的,服务端反正都得做验证,需要应对什么?
gap
2023-10-28 15:50:06 +08:00
我之前看到一个 hack 方案,将状态 hash 后再放到 url param 上去
a632079
2023-10-28 18:23:56 +08:00
Server Components 里我记得可以 Read Cookies ,因此,分页,filter 外的参数,还是使用 Cookies 共享更方便。

Ref: https://nextjs.org/docs/app/api-reference/functions/cookies

P.S NextJS 官方是建议 Server Actions Mutation 时才能修改 Cookies ,RSC 由于 Response 流已经发送,无法设置 Cookies ,但是社区有人做了 Cookies 的方案,实现了 Cookies 共享。
a632079
2023-10-28 18:44:18 +08:00
@hugepizza 看起来应该是支持 revalidate searchParams 的。revalidateTag 就是和 Redis Cache Key ,TanStack Query 的 queryKeys 一样的东西,fetch 是可选设置,第三方数据库比如说 DB 拉来的,就得手动设置 tag 了。

Ref: https://nextjs.org/docs/app/api-reference/functions/unstable_cache (应对第三方数据源的缓存函数)
Ref: https://nextjs.org/docs/app/building-your-application/caching#apis (不同 API 对缓存的影响)
Ref: https://nextjs.org/docs/app/building-your-application/caching#data-cache (Fetch 相关的缓存工作在数据缓存中)
BugCry
2023-10-28 19:31:10 +08:00
@rocmax 既然说到 cookie ,如果加了 http-only 属性,就算是用 js 都读取不出来,然而放 URL 则是完全暴露
rocmax
2023-10-28 20:58:22 +08:00
@BugCry 暴露给客户有什么问题?
BugCry
2023-10-28 21:54:24 +08:00
@rocmax XSS 了解一下
rocmax
2023-10-29 00:55:40 +08:00
@BugCry 从 url 拿到的都是值,react 也会对内容转义,基本不可能会被当成逻辑执行。我的理解将 state 放在 url 里至少不会更不安全。
有什么 xss 的实际例子吗?
Pencillll
2023-10-29 06:59:52 +08:00
1. 所有状态都放 url 里代表着任何人都可以通过 CSRF 的形式来控制页面的初始状态,也就是页面上的所有状态都是不可信的 user input ,所以不仅后端要验证所有数据,连前端也得验证所有数据(状态),否则会和遭受和后端一样的攻击
2. 用户分享链接时大概率会直接复制整个 url 给别人,如果其中包含 token 之类,别人点进来就会直接登入他的账号
3. 浏览器的前进/后退功能会挂掉,比如进入一个新页面,随后修改了主题颜色,这时返回到前一个页面会使修改失效
rocmax
2023-10-29 08:59:07 +08:00
@Pencillll 1. 后台本来验证就不能省,页面反正在客户端,用户怎么折腾又没法管,其他的 state 保存方式并不能避免这些问题。
2. 用户认证是另外的问题,用 url 管理 state 并不会将 token 也存在 url 里。共享带 state 的 url 可以让对方直接到达特定的 app 状态,这其实是优势。
3. 主题颜色不涉及到 client 和 server component 之间的状态传递,放在顶层的 theme provider 里即可。同第二点,这种做法可以让前进/后退在历史状态序列里移动而不是只跳转页面,很多情况下是更方便的。如果针对琐碎的输入不想将每个状态都存入历史,可以在跳转的时候使用 replace 而不是 push 。
yanggggjie
2023-10-31 15:35:05 +08:00
[next-usequerystate - npm]( https://www.npmjs.com/package/next-usequerystate)
op 看看这个库呢

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

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

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

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

© 2021 V2EX