首页 > 解决方案 > 将 SWR 与依赖的请求数据一起使用

问题描述

我正在尝试使用 SWR 获取连接到自定义挂钩提供的登录用户 ID 的用户列表。

我不能放在useSWR里面或者useCallbackuseEffect......if (loggedInAdvisor) { ... }不知道该怎么做。

export const fetchDetailedAdvisorPrognoses = (
  body: DetailedAdvisorPrognosesRequest
): Promise<DetailedAdvisorPrognoses[]> | null => {
  const accessToken = getFromPersistance(ACCESS_TOKEN)

  if (!accessToken) {
    return null
  }

  return fetch('https://x/api/v2/advisors/prognoses', {
    method: 'POST',
    headers: {
      ...generateDefaultHeaders(),
      'Content-Type': 'application/json',
      Authorization: getAuthorizationHeader(accessToken),
    },
    body: JSON.stringify(body), // body data type must match "Content-Type" header
  }).then(res => res.json())
}

function Workload(): ReactElement | null {
  const { loggedInAdvisor } = useAuthentication()

  // yesterday
  const fromDate = moment()
    .subtract(1, 'day')
    .format('YYYY-MM-DD')
  // 14 days ahead
  const toDate = moment()
    .add(13, 'days')
    .format('YYYY-MM-DD')

  const { data, error } = useSWR<DetailedAdvisorPrognoses[] | null>('fetchWorkloadData', () =>
    'detailed',
    fetchDetailedAdvisorPrognoses({
      advisorIds: [loggedInAdvisor.id], // <-- I want to pause the query until loggedInAdvisor is defined 
      fromDate,
      toDate,
    })
  )

  // todo: display errors better
  if (error) {
    return <span>Error: {error.message}</span>
  }

  if (!data) {
    return <LoadingV2 isLoading={!data} />
  }

  if (data && data.length > 0) {
    // advisors prognoses is first element in data array
    const [first] = data
    const days: WorkloadDay[] = Object.keys(first.daysMap).map(date => ({
      date,
      value: first.daysMap[date],
    }))

    return <WorkloadLayout before={first.before} days={days} />
  }

  return null
}

标签: reactjsfetchvercel

解决方案


SWR 支持Conditional Fetching,而不是使用if分支,您需要null作为键传递(这也是 React Hooks 的心理模式):

const { data, error } = useSWR(
  loggedInAdvisor ? 'fetchWorkloadData' : null,
  () => {...}
)

2021/12/10 更新

您还可以获取一些数据,这些数据也基于使用 SWR 的另一个请求的结果:

const { data: user } = useSWR('/api/user', fetcher)
const { data: avatar } = useSWR(user ? '/api/avatar?id=' + user.id : null, fetcher)

在这种情况下,如果user未准备好,第二个请求将不会启动,因为密钥将为null. 当第一个请求结束时,第二个请求将自然启动。这是因为在更改某些数据时总是会发生重新渲染。userundefined

您可以使用此方法以尽可能最佳的并行性获取任意数量的依赖资源。


推荐阅读