Skip to content

Commit

Permalink
feat: React Suspense support in usePublications hook
Browse files Browse the repository at this point in the history
  • Loading branch information
cesarenaldi committed May 7, 2024
1 parent aa460c7 commit 024c1e2
Show file tree
Hide file tree
Showing 10 changed files with 466 additions and 402 deletions.
7 changes: 7 additions & 0 deletions .changeset/brown-guests-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@lens-protocol/react": minor
"@lens-protocol/react-native": minor
"@lens-protocol/react-web": minor
---

**feat:** adds React Suspense support to `usePublications` hook
232 changes: 121 additions & 111 deletions examples/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { XMTPProvider } from '@xmtp/react-sdk';
import { Suspense } from 'react';
import { Toaster } from 'react-hot-toast';
import { Outlet, Route, BrowserRouter as Router, Routes } from 'react-router-dom';

Expand All @@ -9,6 +10,7 @@ import { Providers } from './Providers';
import { GenericErrorBoundary } from './components/GenericErrorBoundary';
import { ErrorMessage } from './components/error/ErrorMessage';
import { Header } from './components/header/Header';
import { Loading } from './components/loading/Loading';
import {
DiscoveryPage,
UseExploreProfiles,
Expand Down Expand Up @@ -101,127 +103,135 @@ export function App() {
<Router>
<Header />
<main>
<GenericErrorBoundary fallback={ErrorMessage}>
<Routes>
<Route index element={<HomePage />} />
<Route path="/login" element={<LogInPage />} />
<Suspense fallback={<Loading />}>
<GenericErrorBoundary fallback={ErrorMessage}>
<Routes>
<Route index element={<HomePage />} />
<Route path="/login" element={<LogInPage />} />

<Route element={<Layout />}>
<Route path="/publications">
<Route index element={<PublicationsPage />} />
<Route path="useCreatePost" element={<UseCreatePost />} />
<Route path="useOptimisticCreatePost" element={<UseOptimisticCreatePost />} />
<Route path="useCreateComment" element={<UseCreateComment />} />
<Route path="useCreateMirror" element={<UseCreateMirror />} />
<Route path="useCreateQuote" element={<UseCreateQuote />} />
<Route path="usePublication" element={<UsePublication />} />
<Route path="usePublications" element={<UsePublications />} />
<Route path="useLazyPublications" element={<UseLazyPublications />} />
<Route
path="useWhoReactedToPublication"
element={<UseWhoReactedToPublication />}
/>
<Route path="useHidePublication" element={<UseHidePublication />} />
<Route path="useReportPublication" element={<UseReportPublication />} />
<Route path="useReactionToggle" element={<UseReactionToggle />} />
<Route path="useBookmarkToggle" element={<UseBookmarkToggle />} />
<Route path="useBookmarks" element={<UseBookmarks />} />
<Route path="useOpenAction" element={<UseOpenAction />} />
<Route path="useNotInterestedToggle" element={<UseNotInterestedToggle />} />
<Route path="useHideCommentToggle" element={<UseHideCommentToggle />} />
</Route>
<Route element={<Layout />}>
<Route path="/publications">
<Route index element={<PublicationsPage />} />
<Route path="useCreatePost" element={<UseCreatePost />} />
<Route path="useOptimisticCreatePost" element={<UseOptimisticCreatePost />} />
<Route path="useCreateComment" element={<UseCreateComment />} />
<Route path="useCreateMirror" element={<UseCreateMirror />} />
<Route path="useCreateQuote" element={<UseCreateQuote />} />
<Route path="usePublication" element={<UsePublication />} />
<Route path="usePublications" element={<UsePublications />} />
<Route path="useLazyPublications" element={<UseLazyPublications />} />
<Route
path="useWhoReactedToPublication"
element={<UseWhoReactedToPublication />}
/>
<Route path="useHidePublication" element={<UseHidePublication />} />
<Route path="useReportPublication" element={<UseReportPublication />} />
<Route path="useReactionToggle" element={<UseReactionToggle />} />
<Route path="useBookmarkToggle" element={<UseBookmarkToggle />} />
<Route path="useBookmarks" element={<UseBookmarks />} />
<Route path="useOpenAction" element={<UseOpenAction />} />
<Route path="useNotInterestedToggle" element={<UseNotInterestedToggle />} />
<Route path="useHideCommentToggle" element={<UseHideCommentToggle />} />
</Route>

<Route path="/profiles">
<Route index element={<ProfilesPage />} />
<Route path="useCreateProfile" element={<UseCreateProfile />} />
<Route path="useProfile" element={<UseProfile />} />
<Route path="useLazyProfile" element={<UseLazyProfile />} />
<Route path="useProfiles" element={<UseProfiles />} />
<Route path="useLazyProfiles" element={<UseLazyProfiles />} />
<Route path="useProfileFollowers" element={<UseProfileFollowers />} />
<Route path="useProfileFollowing" element={<UseProfileFollowing />} />
<Route path="useMutualFollowers" element={<UseMutualFollowers />} />
<Route path="useFollow" element={<UseFollowAndUnfollow />} />
<Route path="useProfileManagers" element={<UseProfileManagers />} />
<Route path="useUpdateProfileManagers" element={<UseUpdateProfileManagers />} />
<Route path="useWhoActedOnPublication" element={<UseWhoActedOnPublication />} />
<Route path="useProfileActionHistory" element={<UseProfileActionHistory />} />
<Route path="useSetProfileMetadata" element={<UseSetProfileMetadata />} />
<Route path="useUpdateFollowPolicy" element={<UseUpdateFollowPolicy />} />
<Route path="useBlockProfiles" element={<UseBlockAndUnblockProfiles />} />
<Route path="useBlockedProfiles" element={<UseBlockedProfiles />} />
<Route path="useReportProfile" element={<UseReportProfile />} />
<Route path="useRecommendProfileToggle" element={<UseRecommendProfileToggle />} />
<Route path="useProfileInterests" element={<UseProfileInterests />} />
</Route>
<Route path="/profiles">
<Route index element={<ProfilesPage />} />
<Route path="useCreateProfile" element={<UseCreateProfile />} />
<Route path="useProfile" element={<UseProfile />} />
<Route path="useLazyProfile" element={<UseLazyProfile />} />
<Route path="useProfiles" element={<UseProfiles />} />
<Route path="useLazyProfiles" element={<UseLazyProfiles />} />
<Route path="useProfileFollowers" element={<UseProfileFollowers />} />
<Route path="useProfileFollowing" element={<UseProfileFollowing />} />
<Route path="useMutualFollowers" element={<UseMutualFollowers />} />
<Route path="useFollow" element={<UseFollowAndUnfollow />} />
<Route path="useProfileManagers" element={<UseProfileManagers />} />
<Route path="useUpdateProfileManagers" element={<UseUpdateProfileManagers />} />
<Route path="useWhoActedOnPublication" element={<UseWhoActedOnPublication />} />
<Route path="useProfileActionHistory" element={<UseProfileActionHistory />} />
<Route path="useSetProfileMetadata" element={<UseSetProfileMetadata />} />
<Route path="useUpdateFollowPolicy" element={<UseUpdateFollowPolicy />} />
<Route path="useBlockProfiles" element={<UseBlockAndUnblockProfiles />} />
<Route path="useBlockedProfiles" element={<UseBlockedProfiles />} />
<Route path="useReportProfile" element={<UseReportProfile />} />
<Route
path="useRecommendProfileToggle"
element={<UseRecommendProfileToggle />}
/>
<Route path="useProfileInterests" element={<UseProfileInterests />} />
</Route>

<Route path="/discovery">
<Route index element={<DiscoveryPage />} />
<Route path="useFeed" element={<UseFeed />} />
<Route path="useFeedHighlights" element={<UseFeedHighlights />} />
<Route path="useSearchPublications" element={<UseSearchPublications />} />
<Route path="useSearchProfiles" element={<UseSearchProfiles />} />
<Route path="useExploreProfiles" element={<UseExploreProfiles />} />
<Route path="useExplorePublications" element={<UseExplorePublications />} />
<Route path="useRecommendedProfiles" element={<UseRecommendedProfiles />} />
</Route>
<Route path="/discovery">
<Route index element={<DiscoveryPage />} />
<Route path="useFeed" element={<UseFeed />} />
<Route path="useFeedHighlights" element={<UseFeedHighlights />} />
<Route path="useSearchPublications" element={<UseSearchPublications />} />
<Route path="useSearchProfiles" element={<UseSearchProfiles />} />
<Route path="useExploreProfiles" element={<UseExploreProfiles />} />
<Route path="useExplorePublications" element={<UseExplorePublications />} />
<Route path="useRecommendedProfiles" element={<UseRecommendedProfiles />} />
</Route>

<Route path="/wallet">
<Route index element={<WalletPage />} />
<Route path="useProfilesManaged" element={<UseProfilesManaged />} />
<Route path="useOwnedHandles" element={<UseOwnedHandles />} />
<Route path="useLastLoggedInProfile" element={<UseLastLoggedInProfile />} />
<Route path="useRateLimits" element={<UseRateLimits />} />
</Route>
<Route path="/wallet">
<Route index element={<WalletPage />} />
<Route path="useProfilesManaged" element={<UseProfilesManaged />} />
<Route path="useOwnedHandles" element={<UseOwnedHandles />} />
<Route path="useLastLoggedInProfile" element={<UseLastLoggedInProfile />} />
<Route path="useRateLimits" element={<UseRateLimits />} />
</Route>

<Route path="/revenue">
<Route index element={<RevenuePage />} />
<Route path="useRevenueFromFollow" element={<UseRevenueFromFollow />} />
<Route path="useRevenueFromPublication" element={<UseRevenueFromPublication />} />
<Route
path="useRevenueFromPublications"
element={<UseRevenueFromPublications />}
/>
</Route>
<Route path="/revenue">
<Route index element={<RevenuePage />} />
<Route path="useRevenueFromFollow" element={<UseRevenueFromFollow />} />
<Route
path="useRevenueFromPublication"
element={<UseRevenueFromPublication />}
/>
<Route
path="useRevenueFromPublications"
element={<UseRevenueFromPublications />}
/>
</Route>

<Route path="/misc">
<Route index element={<MiscPage />} />
<Route path="useNotifications" element={<UseNotifications />} />
<Route path="useCurrencies" element={<UseCurrencies />} />
<Route path="useApproveModule" element={<UseApproveModule />} />
<Route path="useLatestPaidActions" element={<UseLatestPaidActions />} />
<Route path="useClaimHandle" element={<UseClaimHandle />} />
<Route path="useInviteWallets" element={<UseInviteWallets />} />
<Route path="useResolveAddress" element={<UseResolveAddress />} />
<Route path="useValidateHandle" element={<UseValidateHandle />} />
<Route
path="lensClientInteroperability"
element={<LensClientInteroperability />}
/>
<Route path="useSignFrameAction" element={<UseSignFrameAction />} />
</Route>
<Route path="/misc">
<Route index element={<MiscPage />} />
<Route path="useNotifications" element={<UseNotifications />} />
<Route path="useCurrencies" element={<UseCurrencies />} />
<Route path="useApproveModule" element={<UseApproveModule />} />
<Route path="useLatestPaidActions" element={<UseLatestPaidActions />} />
<Route path="useClaimHandle" element={<UseClaimHandle />} />
<Route path="useInviteWallets" element={<UseInviteWallets />} />
<Route path="useResolveAddress" element={<UseResolveAddress />} />
<Route path="useValidateHandle" element={<UseValidateHandle />} />
<Route
path="lensClientInteroperability"
element={<LensClientInteroperability />}
/>
<Route path="useSignFrameAction" element={<UseSignFrameAction />} />
</Route>

<Route
path="/inbox"
element={
<XMTPProvider>
<Outlet />
</XMTPProvider>
}
>
<Route index element={<InboxPage />} />
<Route path="useEnhanceConversations" element={<UseEnhanceConversations />} />
<Route
path="useEnhanceConversation/:conversationId"
element={<UseEnhanceConversation />}
/>
<Route path="useStartLensConversation" element={<UseStartLensConversation />} />
path="/inbox"
element={
<XMTPProvider>
<Outlet />
</XMTPProvider>
}
>
<Route index element={<InboxPage />} />
<Route path="useEnhanceConversations" element={<UseEnhanceConversations />} />
<Route
path="useEnhanceConversation/:conversationId"
element={<UseEnhanceConversation />}
/>
<Route path="useStartLensConversation" element={<UseStartLensConversation />} />
</Route>
</Route>
</Route>

<Route path="*" element={<p>Not found</p>} />
</Routes>
</GenericErrorBoundary>
<Route path="*" element={<p>Not found</p>} />
</Routes>
</GenericErrorBoundary>
</Suspense>
<Toaster />
</main>
</Router>
Expand Down
10 changes: 6 additions & 4 deletions examples/web/src/hooks/useInfiniteScroll.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { PaginatedReadResult } from '@lens-protocol/react-web';
import { RefCallback } from 'react';
import { SuspendablePaginatedResult } from '@lens-protocol/react-web';
import { RefCallback, startTransition } from 'react';
import { useInView } from 'react-cool-inview';

export function useInfiniteScroll<T, Q extends PaginatedReadResult<T> = PaginatedReadResult<T>>(
export function useInfiniteScroll<T, Q extends SuspendablePaginatedResult<T>>(
queryResult: Q,
): Q & { observeRef: RefCallback<unknown> } {
const { observe: observeRef } = useInView({
// Grow the root margin so the data will be loaded earlier
rootMargin: '20% 0px',
onEnter: async ({ unobserve, observe }) => {
unobserve();
await queryResult.next();
startTransition(() => {
void queryResult.next();
});
observe();
},
});
Expand Down
24 changes: 10 additions & 14 deletions examples/web/src/publications/UsePublications.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { PublicationType, profileId, usePublications } from '@lens-protocol/react-web';
import { useState } from 'react';
import { LimitType, PublicationType, profileId, usePublications } from '@lens-protocol/react-web';
import { startTransition, useState } from 'react';

import { PublicationCard } from '../components/cards';
import { ErrorMessage } from '../components/error/ErrorMessage';
import { Loading } from '../components/loading/Loading';
import { useInfiniteScroll } from '../hooks/useInfiniteScroll';

const allPublicationType = [PublicationType.Comment, PublicationType.Post, PublicationType.Mirror];
Expand All @@ -13,24 +11,24 @@ export function UsePublications() {

const {
data: publications,
beforeCount,
error,
loading,
hasMore,
prev,
observeRef,
} = useInfiniteScroll(
usePublications({
where: {
from: [profileId('0x06')],
from: [profileId('0x05')],
publicationTypes: publicationType,
},
limit: LimitType.Ten,
suspense: true,
}),
);

if (loading) return <Loading />;

if (error) return <ErrorMessage error={error} />;
const refresh = () =>
startTransition(() => {
void prev();
});

return (
<div>
Expand Down Expand Up @@ -60,9 +58,7 @@ export function UsePublications() {
))}
</fieldset>

<button disabled={loading || beforeCount === 0} onClick={prev}>
Fetch newer
</button>
<button onClick={refresh}>Refresh</button>

{publications.map((publication) => (
<PublicationCard key={publication.id} publication={publication} />
Expand Down
Loading

0 comments on commit 024c1e2

Please sign in to comment.