toss / suspensive

Manage asynchronous operations, timing, error handling, detecting intersection of elements, and caching easily and declaratively (One of TanStack Query community resources)
https://suspensive.org
MIT License
479 stars 45 forks source link

[Feature]: Support lazy load `<InView />` #1071

Open manudeli opened 1 month ago

manudeli commented 1 month ago

Package Scope

etc

Description

@suspensive/intersection to trigger fetch on view inside of window

Possible Solution

const posts = useSuspenseQuery(postsQueryOptions(...))

return posts.map((post) => (
    <Intersection fallback={<Skeleton />}>
      <Suspense fallback={<Skeleton />}>
        <SuspenseQuery {postQueryOptions(post.id)}>
          {(post) => <Post {...post} />}
        </SuspenseQuery>
      </Suspense>
    </Intersection>
  )
)

etc.

No response

manudeli commented 1 month ago
const posts = useSuspenseQuery(postsQueryOptions(...))

return posts.map((post) => (
  <Suspense intersection fallback={({ intersectionRef }) => <Skeleton ref={intersectionRef} />}>
    <SuspenseQuery {postQueryOptions(post.id)}>
      {(post) => <Post {...post} />}
    </SuspenseQuery>
  </Suspense>
  )
)

@gwansikk @kangju2000 @bigsaigon333 This could be new intersection prop of Suspense to lazy load??

gwansikk commented 1 month ago
const posts = useSuspenseQuery(postsQueryOptions(...))

return posts.map((post) => (
  <Suspense intersection fallback={({ intersectionRef }) => <Skeleton ref={intersectionRef} />}>
    <SuspenseQuery {postQueryOptions(post.id)}>
      {(post) => <Post {...post} />}
    </SuspenseQuery>
  </Suspense>
  )
)

@gwansikk @kangju2000 @bigsaigon333 This could be new intersection prop of Suspense to lazy load??

Oh, that's a great idea! It seems useful for gradually loading the necessary data for users through lazy loading

minsoo-web commented 1 month ago

How about this interface ?

const posts = useSuspenseQuery(postsQueryOptions(...))

<Suspense when="intersectionObserve"></Suspense>
<Suspense when="render"></Suspense> // default
<Suspense triggerBy="intersectionObserve"></Suspense>
<Suspense triggerBy="render"></Suspense>  // default

I think the intersection prop is too much of an abstraction. What you want to do is determine the moment that creates the suspense, so I'm thinking of something like a trigger or a when.

minsoo-web commented 1 month ago

However, I think Intersection Observe should have more options.

For example,

rootMargin thresholds

I thought, "How do I set these options?"

minsoo-web commented 1 month ago
const posts = useSuspenseQuery({
  ...otherOptions,
  observeRef: ref
})

return <div ref={ref}

How about this approach: if we get a ref, we'll treat it like an enable, and it'll work then, so the user doesn't have to know about the intersection observe api.

manudeli commented 1 month ago

We should support react-native and web at once too!

manudeli commented 1 month ago
<InView>
  {(trigger) => (
    <div ref={trigger.ref}>
      <Suspense enabled={trigger.isInView} fallback={<Spinner/>}>
        <SuspensQuery />
      </Suspense>
    </div>
  )}
</InView>
manudeli commented 1 month ago
<InView>
  {(target) => (
    <div ref={target.ref}>
      <Suspense fallback={<Spinner/>}>
        {target.isInView ? <SuspensQuery/> : <SuspenseAllTime/>}
      </Suspense>
    </div>
  )}
</InView>