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

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

  •  
  •   rocmax · 2023-10-28 08:27:35 +08:00 via Android · 1618 次点击
    这是一个创建于 421 天前的主题,其中的信息可能已经有所发展或是发生改变。

    由于 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

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

    13 条回复    2023-10-31 15:35:05 +08:00
    BugCry
        1
    BugCry  
       2023-10-28 11:23:13 +08:00 via Android
    1 ,URL 的长度有限制
    2 ,如果 state 被恶意修改,阁下将如何应对?
    hugepizza
        2
    hugepizza  
       2023-10-28 11:53:33 +08:00
    cache revalidate 也是个问题 官方文档上的 revalidatePath 没有写是否支持 searchParams
    至于 revalidateTag 我到现在也没搞懂这是个啥 🤣
    rocmax
        3
    rocmax  
    OP
       2023-10-28 11:56:23 +08:00 via Android
    @BugCry 1 确实是一个硬性的限制,浏览器限制在 2048 字符以下,一般而言是够的,如果把使用 url 存储 state 作为一个原则的话可能会遇到极端情况无法处理。长 url 还会带来难以记录和共享的问题,优势是能将 app 恢复到特定状态。
    第 2 点风险在哪里?客户端 state 本来就存在客户端,不管存在 context ,localstorage 还是 cookie 里,客户都是随便改的,服务端反正都得做验证,需要应对什么?
    gap
        4
    gap  
       2023-10-28 15:50:06 +08:00 via iPhone
    我之前看到一个 hack 方案,将状态 hash 后再放到 url param 上去
    a632079
        5
    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
        6
    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
        7
    BugCry  
       2023-10-28 19:31:10 +08:00 via Android
    @rocmax 既然说到 cookie ,如果加了 http-only 属性,就算是用 js 都读取不出来,然而放 URL 则是完全暴露
    rocmax
        8
    rocmax  
    OP
       2023-10-28 20:58:22 +08:00 via Android
    @BugCry 暴露给客户有什么问题?
    BugCry
        9
    BugCry  
       2023-10-28 21:54:24 +08:00 via Android
    @rocmax XSS 了解一下
    rocmax
        10
    rocmax  
    OP
       2023-10-29 00:55:40 +08:00
    @BugCry 从 url 拿到的都是值,react 也会对内容转义,基本不可能会被当成逻辑执行。我的理解将 state 放在 url 里至少不会更不安全。
    有什么 xss 的实际例子吗?
    Pencillll
        11
    Pencillll  
       2023-10-29 06:59:52 +08:00
    1. 所有状态都放 url 里代表着任何人都可以通过 CSRF 的形式来控制页面的初始状态,也就是页面上的所有状态都是不可信的 user input ,所以不仅后端要验证所有数据,连前端也得验证所有数据(状态),否则会和遭受和后端一样的攻击
    2. 用户分享链接时大概率会直接复制整个 url 给别人,如果其中包含 token 之类,别人点进来就会直接登入他的账号
    3. 浏览器的前进/后退功能会挂掉,比如进入一个新页面,随后修改了主题颜色,这时返回到前一个页面会使修改失效
    rocmax
        12
    rocmax  
    OP
       2023-10-29 08:59:07 +08:00 via Android
    @Pencillll 1. 后台本来验证就不能省,页面反正在客户端,用户怎么折腾又没法管,其他的 state 保存方式并不能避免这些问题。
    2. 用户认证是另外的问题,用 url 管理 state 并不会将 token 也存在 url 里。共享带 state 的 url 可以让对方直接到达特定的 app 状态,这其实是优势。
    3. 主题颜色不涉及到 client 和 server component 之间的状态传递,放在顶层的 theme provider 里即可。同第二点,这种做法可以让前进/后退在历史状态序列里移动而不是只跳转页面,很多情况下是更方便的。如果针对琐碎的输入不想将每个状态都存入历史,可以在跳转的时候使用 replace 而不是 push 。
    yanggggjie
        13
    yanggggjie  
       2023-10-31 15:35:05 +08:00
    [next-usequerystate - npm]( https://www.npmjs.com/package/next-usequerystate)
    op 看看这个库呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 13:24 · PVG 21:24 · LAX 05:24 · JFK 08:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.