react-query 踩坑

3,003 阅读3分钟

一般而言, 使用原生的async 函数来包装请求逻辑, 直到 await 返回才会执行后面的代码,但是 useQuery, 即使还未fetching,下面的代码就会执行, 一是需要?.判断, 二是数据是残缺的

残缺的 意思就是 一个变量, 由静态部分和异步部分组成的, 当异步还未返回时,他只有静态部分, 假如你的逻辑是异步返回时运行,那么没有任何问题,但是由于useQuery下面的代码是同步的,不等接口返回 组件立刻使用这部分残缺的数据去render,导致产生很多中间态, 也就产生很多bug

感觉, 这是为了解决瀑布流问题而引出的新问题, 但是中后台项目,需要的是低bug,而不是那点微薄的,由于接口导致的页面性能, 移动端项目在乎页面性能, 但是更不可能使用这么大size的库去解决这个问题

不要把它当作请求hook使用

存在的问题:

查询表单场景

image.png

useQuery在页面层调用,就很简单,这里不讲

假设useQuery是封装在 Table里,请不要把symbol放进依赖, 否则 symbol + useEffect + setPage(1) 会触发两次请求,正确的方式是按照以下方法

最好不要使用ref来主动调用, 因为跟react-query的观念不一样,容易出bug

// symbol 是一个自增的数字, 每次点击submit就生成,用于表示点击了submit按钮
const Table = ({symbol})=> {
const [page,setPage] = useState(1)

const url = '/api'
const body = {}

const { refetch } = useQuery([url,queryKey],()=>axios({url,body:body }))

useEffect(() => {
    if (page === 1) {
      refetch() // 不接受参数, 即使form改变,理应又发起一次,但是refetch会使用最新的queryKey,两次queryKey相同,所以只会保留一个请求
    } else {
    // 查询时,如果不在第一页,则回第一个, 依靠queryKey的改变,自发请求
      setPage(1)
    }
  }, [symbol])

}

一开始肯定想到把symbol放queryKey, 可以也可以,但没必要

  • 除非维护上一次的序列化后的queryKey, symbol改变了时与之比较,来推测react-quey是否会请求

总之, 需要对react-query 比较熟悉才能想到以上代码, 心智负担太大, 完全不推荐这种束缚想法的垃圾,相反推荐swr

一. react-query vs swr

// 手动调用
const {refetch/* 不支持传参 */ } = useQuery() // react-query
const {mutate/* 支持传参 */} = useSwr([URL,params])=>fetch(URL,{body:params})) // swr

swrreact-query:

  1. 所有请求参数都放 queryKey(必须所有,未加入的值会一直用同一个值)

一个场景: 请求参数有数组,但是数组顺序改变时,期望不要请求,像这种依赖key的请求库,很难hold住多变的场景,

这个场景下,react-query 完全hold不住, 只能自己曲线救国, 重排序数组,这样无论是否变动,都会重排

另外, swr2 添加了纯手动的api useSWRMutation,我以为可以抛弃queryKey这种垃圾设计了, 但是试用了一下, 不支持使用全局 mutate 来重新触发该请求, 某些时候需要全页面重新请求时,就hold不住,

提了个issue, 如果官方认为是issue, 并且修复了, 那我就推荐swr, 具体可查看该issue,否则还是别用这两垃圾吧