Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: useSWRAggregator #2018

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

Conversation

promer94
Copy link
Collaborator

@promer94 promer94 commented Jun 9, 2022

This pr is trying to explore a possible solution for #1041 and #1988

Motivation

In most of time, if users want to render a list of useSWR hooks, they could do something like this.

const Item = ({ swrKey }) => {
  const { data } = useSWR(swrKey, fetcher)
  return <div>{data ? data : 'loading'}</div>
}
const Demo = () => {
  const [keys] = useState(['/api/data?id=0', '/api/data?id=1', '/api/data?id=2'])
  return <div>{keys.map(v => <Item key={v} swrKey={v} />)}</div>
}

But this pattern has some problems

  • too much boilerplate code.
  • user has to create key for their item component. comment
  • user could not access aggregate result of swr hooks. comment

useSWRAggregator

Design

  • using render props to reduce boilerplate code
  • key for item component will be created by swr's build-in serialization
  • user can access aggregate result from the result of useSWRAggregator and render props

Usage

  • Simple
const Demo = () => {
  const { data } = useSWRAggregator(keys, fetch)
  return <>{data.map(v => <div key={v.key}>{v.data ? v.data : v.error.toString()}</div>)}</>
}
  • Render props
const Demo = () => {
  const { items } = useSWRAggregator(keys, fetch, {
    keepPreviousData: true,
    children: (swrResult, index, swrAggregator) => {
      return <div>{swrResult.data ? swrResult.data : "loading"}</div>;
    }
  })
  return <>{items}</>
}
  • Toghter
const Demo = () => {
  const { data, items } = useSWRAggregator(keys, fetch, {
    keepPreviousData: true,
    children: (value, index, array) => {
      return <div>{value.data ? value.data : 'loading'}</div>
    }
  })
  return (
    <div>
      <div>{items}</div>
      <div>
        {data ? (
          data.map(v => (
            <div key={v.key}>{v.data ? v.data : v.error.toString()}</div>
          ))
        ) : (
          <div>loading</div>
        )}
      </div>
    </div>
  )
}

Problems

  • Item component will use useSWR internally, it wouldn't share config with useSWRAggregator and needs extra code to config useSWR
const Demo = () => {
  const { items } = useSWRAggregator(keys, fetch, {
    keepPreviousData: true,
    children: (value, index, array) => {
      return <div>{value.data ? value.data : 'loading'}</div>
    }
  })
  // Has to use SWRConfig config useSWR in items
  return <SWRConfig value={yourconfig}>{items}</SWRConfig>
}

config individually

const Demo = () => {
  const { items } = useSWRAggregator(keys, fetch, {
    keepPreviousData: true,
    children: (value, index, array) => {
      return <div>{value.data ? value.data : 'loading'}</div>
    }
  })
  // Has to use SWRConfig config useSWR in items
  return items.map(v => <SWRConfig value={yourconfig}>{items}</SWRConfig>)
}

Demo

https://codesandbox.io/s/useswraggregator-je1dxf

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jun 9, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit be97fb9:

Sandbox Source
SWR-Basic Configuration
SWR-States Configuration
SWR-Infinite Configuration
SWR-SSR Configuration
useSWRAggregator PR

@promer94 promer94 changed the title WIP: useSWRList WIP: useSWRAggregator Jun 14, 2022
chroe: update
@0xbe1
Copy link

0xbe1 commented Dec 2, 2022

any plan on crossing the finish line? look forward to using this feature

@Conmiro
Copy link

Conmiro commented Dec 14, 2022

Would also like to utilize this! We have a workaround that involves looping thru the list of service calls, creating a component for each which uses the useSwr() hook, then utilizes a callback/reducer to send the data back to the parent which aggregates everything.

Our particular use case is we have data that's loading in different components throughout the page, but then also have a component that needs to know the status of which panels have had their data loaded already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants