SWR:用于数据请求的React Hook库

使用 SWR,组件将会不断地自动获得最新数据流。
UI 也会一直保持快速响应

仅需一行代码,你就可以简化项目中数据请求的逻辑,并立即拥有以下这些不可思议的特性:

  • 极速轻量可重用的 数据请求
  • 内置 缓存 和重复请求去除
  • 实时 体验
  • 传输和协议不可知
  • 支持 SSR / ISR / SSG
  • 支持 TypeScript
  • React Native

SWR 涵盖了性能,正确性和稳定性的各个方面,以帮你建立更好的体验:

  • 快速页面导航
  • 间隔轮询
  • 数据依赖
  • 聚焦时重新验证
  • 网络恢复时重新验证
  • 本地缓存更新 (Optimistic UI)
  • 智能错误重试
  • 分页和滚动位置恢复
  • React Suspense

入门

安装

在 React 项目目录运行以下命令:

npm install swr

快速开始

对于返回 JSON 数据的普通 RESTful APIs,首先需要创建一个 fetcher 函数,这个函数只是原生 fetch 的包装:

const fetcher = (...args) => fetch(...args).then((res) => res.json())

然后你可以 import useSWR 并开始在任何函数组件中使用它:

import useSWR from "swr";

function Profile() {
  const { data, error, isLoading } = useSWR("/api/user/123", fetcher)

  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>

  // 渲染数据
  return <div>hello {data.name}!</div>
}

可复用组件

在构建 web 应用时,你可能需要在 UI 的很多地方重用数据。在 SWR 上创建可重用的数据 hooks 非常容易:

function useUser(id) {
  const { data, error, isLoading } = useSWR(`/api/user/${id}`, fetcher)

  return {
    user: data,
    isLoading,
    isError: error,
  }
}

在组件中使用:

function Avatar({ id }) {
  const { user, isLoading, isError } = useUser(id)

  if (isLoading) return <Spinner />
  if (isError) return <Error />
  return <img src={user.avatar} />
}

全局配置

SWRConfig 可以为所有的 SWR hook 提供全局配置。

<SWRConfig value={options}>
  <Component/>
</SWRConfig>

在以下示例中,所有的 SWR hook 都将使用提供的相同的 fetcher 来加载 JSON 数据,默认每 3 秒刷新一次:

import useSWR, { SWRConfig } from 'swr'

function Dashboard () {
  const { data: events } = useSWR('/api/events')
  const { data: projects } = useSWR('/api/projects')
  const { data: user } = useSWR('/api/user', { refreshInterval: 0 }) // override

  // ...
}

function App () {
  return (
    <SWRConfig 
      value={{
        refreshInterval: 3000,
        fetcher: (resource, init) => fetch(resource, init).then(res => res.json())
      }}
    >
      <Dashboard />
    </SWRConfig>
  )
}

数据请求

const { data, error } = useSWR(key, fetcher)

这是 SWR 的基本 API。这里的 fetcher 是一个异步函数,它 接受 SWR 的 key 并返回数据。

返回值将作为 data 传递,如果抛出错误,将作为 error 被捕获。

axios

import axios from 'axios'

const fetcher = url => axios.get(url).then(res => res.data)

function App () {
  const { data, error } = useSWR('/api/data', fetcher)
  // ...
}

条件数据请求

按需请求

使用 null 或传一个函数作为 key 来有条件地请求数据。如果函数抛出错误或返回 falsy 值,SWR 将不会启动请求。

// 有条件的请求
const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)

// ...或返回一个 falsy 值
const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)

// ... 或在 user.id 未定义时抛出错误
const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)

传入参数

参数

默认情况下,key 将作为参数传递给 fetcher。所以下面这 3 个表达式是等价的:

useSWR('/api/user', () => fetcher('/api/user'))
useSWR('/api/user', url => fetcher(url))
useSWR('/api/user', fetcher)

多个参数

在某些场景中,向 fetcher 函数传递多个参数(可以是任何值或对象)非常有用。

例如授权请求:

useSWR('/api/user', url => fetchWithToken(url, token))

数据更改

SWR 提供了 mutateuseSWRMutation 两个 API 用于更改远程数据及相关缓存。

mutate

有两种方法可以使用 mutate API 来进行数据更改,全局数据更改 API 可以更改任何 key 的数据,而绑定数据更改只能更改对应 SWR hook 的数据。

全局数据更改

推荐使用 useSWRConfig hook 获取全局 mutator

import { useSWRConfig } from "swr"

function App() {
  const { mutate } = useSWRConfig()
  mutate(key, data, options)
}

全局引入它:

import { mutate } from "swr"

function App() {
  mutate(key, data, options)
}
绑定数据更改

绑定数据更改可以更便捷的更改当前 key 数据,它的 key 与传递给 useSWRkey 相绑定,并接收 data 作为第一个参数。

它在功能上等同于上文提到的的全局 mutate 函数,但它不需要传入 key 参数:

import useSWR from 'swr'

function Profile () {
  const { data, mutate } = useSWR('/api/user', fetcher)

  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button onClick={async () => {
        const newName = data.name.toUpperCase()
        // 发送请求给 API 以更新数据
        await requestUpdateUsername(newName)
        // 立即更新并重新验证本地数据(重新请求)
        // 注意: 当使用 useSWR 的 mutate 时,key 并不是必须的,因为它已经预先绑定了。
        mutate({ ...data, name: newName })
      }}>Uppercase my name!</button>
    </div>
  )
}
Api
Parameters
  • key:与 useSWRkey 相同,但函数表现为一个 过滤函数

  • data:用于更新客户端缓存的数据,或者是一个用于进行远程数据更改的异步函数。

  • options
    

    :接受下列选项

    • optimisticData:用于立即更新客户端缓存的数据,或是一个接受当前数据并返回新的客户端缓存数据的函数,通常用于乐观 UI。
    • revalidate = true:一旦异步更新完成,重新验证缓存。
    • populateCache = true:将远程数据更改的结果写入缓存,或者将接收新结果和当前结果作为参数并返回数据更改结果的函数。
    • rollbackOnError = true:如果远程数据更改失败,缓存会回滚。或者接受一个函数,它接收从 fetcher 抛出的错误作为参数,并返回一个布尔值判断是否应该回滚。
    • throwOnError = true:数据更改失败时抛出错误。
返回值

mutate 返回参数的 data 是被解析过的结果。传递给 mutate 的函数将返回一个更新后的数据,用于更新相应的缓存值。如果在执行函数时出现错误,错误将被抛出,以便进行合适的处理。

try {
  const user = await mutate('/api/user', updateUser(newUser))
} catch (error) {
  // 处理更新用户时出现的错误
}

useSWRMutation

SWR 还提供了 useSWRMutation 作为一个远程数据更改的 hook。远程数据更改只能手动触发,而不像 useSWR 那样会自动触发。

另外,这个 hook 不会与其他 useSWRMutation hook 共享状态。

import useSWRMutation from 'swr/mutation'

// 实现 fetcher
// 额外的参数可以通过第二个参数 `arg` 传入
// 在下例中,`arg` 为 `'my_token'`
async function updateUser(url, { arg }) {
  await fetch(url, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${arg}`
    }
  })
}

function Profile() {
  // 一个类似 useSWR + mutate 的 API,但是它不会自动发送请求
  const { trigger } = useSWRMutation('/api/user', updateUser, options?)

  return <button onClick={() => {
    // 以特定参数触发 `updateUser` 函数
    trigger('my_token')
  }}>Update User</button>
}
Api
参数
  • key: 与 mutatekey 相同

  • fetcher(key, { arg }):一个用于远程数据更改的异步函数

  • options
    

    :一个可选的对象,包含了下列属性:

    • optimisticData:与 mutateoptimisticData 相同
    • revalidate = true:与 mutaterevalidate 相同
    • populateCache = false:与 mutate’ 的 populateCache 相同 ,但默认值为 false
    • rollbackOnError = true:与 mutaterollbackOnError 相同
    • throwOnError = true: 与 mutate’ 的 throwOnError 相同
    • onSuccess(data, key, config): 远程数据更改完成时的回调函数
    • onError(err, key, config): 远程数据更改返回错误时的回调函数
返回值
  • data:从 fetcher 返回给定 key 的数据
  • errorfetcher 中抛出的错误(或 undefined)
  • trigger(arg, options):一个用于触发远程数据更改的函数
  • reset:一个用于重置状态的函数( data, error, isMutating
  • isMutating:有一个正在进行中的远程数据变更
基本用法
import useSWRMutation from 'swr/mutation'

async function sendRequest(url, { arg }) {
  return fetch(url, {
    method: 'POST',
    body: JSON.stringify(arg)
  }).then(res => res.json())
}

function App() {
  const { trigger, isMutating } = useSWRMutation('/api/user', sendRequest, /* options */)

  return (
    <button
      disabled={isMutating}
      onClick={async () => {
        try {
          const result = await trigger({ username: 'johndoe' }, /* options */)
        } catch (e) {
          // 错误处理
        }
      }}
    >
      Create User
    </button>
  )
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值