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

提问一个 React 的问题

  •  
  •   Plumbiu ·
    Plumbiu · 22 天前 · 1647 次点击

    像是 fetch 这种请求,需要根据某个 state 变化重新请求,例如 pageSize ,大家一般用以下哪种写法(或者自己有更好的也可说一下):

    useEffect:

    useEffect(() => {
    	fetch(`xxx?pageSize=${pageSize}`)
    }, [pageSize])
    

    在 state 发生变化的组件调用 fetch:

    <Pagination
      pageSize={pageSize}
      onChange={(pageSize) => {
        fetch(`xxx?pageSize=${pageSize}`)
      }}
    />
    

    我个人更倾向第二种,第一种 useEffect 看上去更方便,不用第二种需要在每个 state 变化的组件调用 fetch ,但是长期维护下来可能会有意想不到的 bug (公司里有个项目因为缓存的 code 和后端返回的 code 不同,导致 useEffect 调用了两边,自己 dev 环境下 mock 很难察觉)

    20 条回复    2025-07-12 17:19:27 +08:00
    foolishcrab
        1
    foolishcrab  
       22 天前 via iPhone   ❤️ 1
    这是 react fc 出来以后讨论了好几年的问题了,没什么价值。
    写第一种的人早就下班了,你从页面上点半天也点不出他什么 bug, 而你还在加班欣赏你优雅的代码。
    另外 in practice 第二种绝对是更复杂的,你举一个多参数接口的例子就知道了
    donaldturinglee
        2
    donaldturinglee  
       22 天前 via Android
    第二种比较好的做法是 onChange={handle PageSize},但是这种方式写起来也挺痛苦的
    vace
        3
    vace  
       22 天前   ❤️ 1
    const [ pageSize, setPageSize ] = useState(10)

    const { data } = useSWR(`xxx?pageSize=${pageSize}`, fetch)

    <Pagination pageSize={pageSize} onChange={setPageSize} />
    realkaiway
        4
    realkaiway  
       22 天前 via iPhone   ❤️ 2
    我劝你早点用 TanStack Query ,早下班,还优雅
    darkengine
        5
    darkengine  
       22 天前
    真实情况下,除了 pageSize 还有其他条件,例如 page ,还有 gender 这些,你怎么处理的?
    twk93
        6
    twk93  
       22 天前
    单从问题的两个选择来看肯定选第一个,代码好维护。更好的方案就是楼上说的使用 TanStack Query
    BeijingBaby
        7
    BeijingBaby  
       21 天前
    react-query
    dabingbing
        8
    dabingbing  
       21 天前
    第一种啊, 两次那是严格模式,生产不会两次
    hwdq0012
        9
    hwdq0012  
       21 天前
    严格模式会调 react 函数两次,帮你确定是否是 纯函数
    ps:我学 react native 时从文档上看到的,好奇楼主是从哪个途径学习的
    yhxx
        10
    yhxx  
       21 天前
    现在流行的是这样的:
    const { data, isLoading } = useQuery(['data', page, pageSize], () =>
    fetch(`xxx?page=${page}&pageSize=${pageSize}`).then(res => res.json())
    )

    你提的两种选一个的话应该是第一种好一些
    kamilic
        11
    kamilic  
       21 天前
    react-query or swr 都支持 pagination 的特性
    HowardTang
        12
    HowardTang  
       21 天前
    TanStack Query / useSwr
    gkinxin
        13
    gkinxin  
       21 天前
    https://zh-hans.react.dev/learn/you-might-not-need-an-effect#how-to-remove-unnecessary-effects (你不必使用 Effect 来处理用户事件)
    第二种更好,官方已经有指南了,因为你是明确知道什么时候需要改变 pageSize 的。
    Asuler
        14
    Asuler  
       21 天前
    选第二种,因为第一种有很恶心的闭包问题,你现在只是写了 pageSize 这个参数而已,实际情况可能还有很多表单参数,你在这里面都拿不到最新的。到时候你要维护,你就不断地往 useEffect 的[]里加,一更新就触发调用了,然而用户更多是想点击查询按钮的时候再去调用接口,而不是表单每个值填上后就触发调接口,到时候你维护起来还得加一堆 if 判断
    dabennn
        15
    dabennn  
       21 天前
    能不用 useEffect 就不用 useEffect ,参数多起来互相打架,改都改不动
    realJamespond
        16
    realJamespond  
       21 天前
    swr 和 qeury ,不用的就是刚入门的
    Plumbiu
        17
    Plumbiu  
    OP
       20 天前
    @realkaiway 用了下班更晚了哈哈哈,这要多久才能改造完
    Plumbiu
        18
    Plumbiu  
    OP
       20 天前
    @vace 我很好奇这种库和第一种差别,除了封装好更简洁,还有其他好处吗,因为我第一眼觉得 useSWR 参数变了,不还是要重新请求,假如我有个参数 scene ,只有后端区分场景,前端 ui 不可见,使用 uesRef 保存,state 更新岂不会发起二次请求
    Plumbiu
        19
    Plumbiu  
    OP
       20 天前
    @Plumbiu 像是这种,模拟了一下 ```jsx

    import { useEffect, useRef, useState } from 'react'

    function useSWR(url: string) {
    useEffect(() => {
    console.log(url)
    }, [url])
    }

    function App() {
    const sceneRef = useRef<number>(0)
    const [count, setCount] = useState(0)
    useSWR(`/?scene=${sceneRef.current}`)

    return (
    <>
    <div>{count}</div>
    <button
    onClick={() => {
    setCount(count + 1)
    sceneRef.current = count
    }}
    >
    count+
    </button>
    </>
    )
    }

    export default App

    ```
    hzzhzzdogee
        20
    hzzhzzdogee  
       19 天前
    非专业前端, 个人推崇 swr
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1073 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:01 · PVG 07:01 · LAX 16:01 · JFK 19:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.