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

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

  •  
  •   rocmax · 183 天前 via Android · 1281 次点击
    这是一个创建于 183 天前的主题,其中的信息可能已经有所发展或是发生改变。

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