diff --git a/src/hooks/auth/useOAuth.ts b/src/hooks/auth/useOAuth.ts index 90f917d1..3cc4926d 100644 --- a/src/hooks/auth/useOAuth.ts +++ b/src/hooks/auth/useOAuth.ts @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { OAuthProvider } from '~/types/auth'; import { API } from '~/constants/api'; import { apiAttachSocial, apiDropSocial, apiGetSocials, apiLoginWithSocial } from '~/api/auth'; @@ -89,13 +89,15 @@ export const useOAuth = () => { [mutate] ); + const accounts = useMemo(() => data || [], [data]); + return { openOauthWindow, loginWithSocial, createSocialAccount, attachAccount, dropAccount, - accounts: data || [], + accounts, isLoading: !data && isLoading, }; }; diff --git a/src/hooks/comments/useGetComments.ts b/src/hooks/comments/useGetComments.ts index 0f530336..605ea67d 100644 --- a/src/hooks/comments/useGetComments.ts +++ b/src/hooks/comments/useGetComments.ts @@ -3,7 +3,7 @@ import { flatten, isNil } from 'ramda'; import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; import { apiGetNodeComments } from '~/api/node'; import { COMMENTS_DISPLAY } from '~/constants/node'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { IComment } from '~/types'; const getKey: (nodeId: number) => SWRInfiniteKeyLoader = (nodeId: number) => ( @@ -41,7 +41,7 @@ export const useGetComments = (nodeId: number) => { } ); - const comments = flatten(data || []); + const comments = useMemo(() => flatten(data || []), [data]); const hasMore = (data?.[size - 1]?.length || 0) >= COMMENTS_DISPLAY; const onLoadMoreComments = useCallback(() => setSize(size + 1), [setSize, size]); diff --git a/src/hooks/flow/useFlow.ts b/src/hooks/flow/useFlow.ts index 1514f0a4..d1d0fea8 100644 --- a/src/hooks/flow/useFlow.ts +++ b/src/hooks/flow/useFlow.ts @@ -2,7 +2,6 @@ import { useFlowLayout } from '~/hooks/flow/useFlowLayout'; import { useMemo } from 'react'; import { useFlowLoader } from '~/hooks/flow/useFlowLoader'; import { useFlowStore } from '~/store/flow/useFlowStore'; -import { useInfiniteLoader } from '~/hooks/dom/useInfiniteLoader'; import { useFlowSetCellView } from '~/hooks/flow/useFlowSetCellView'; import { useGetLabStats } from '~/hooks/lab/useGetLabStats'; @@ -13,10 +12,19 @@ export const useFlow = () => { const { isFluid, toggleLayout } = useFlowLayout(); const lab = useGetLabStats(); - useInfiniteLoader(loadMore, isSyncing); - const updates = useMemo(() => [...updated, ...lab.updates].slice(0, 10), [lab.updates, updated]); const onChangeCellView = useFlowSetCellView(); - return { nodes, heroes, recent, updates, isFluid, toggleLayout, onChangeCellView }; + + return { + nodes, + heroes, + recent, + updates, + isFluid, + toggleLayout, + onChangeCellView, + loadMore, + isSyncing, + }; }; diff --git a/src/hooks/lab/useGetLabNodes.ts b/src/hooks/lab/useGetLabNodes.ts index 6da2173f..4dcd6b8c 100644 --- a/src/hooks/lab/useGetLabNodes.ts +++ b/src/hooks/lab/useGetLabNodes.ts @@ -3,7 +3,7 @@ import { GetLabNodesRequest, ILabNode } from '~/types/lab'; import { getLabNodes } from '~/api/lab'; import { flatten, last, uniqBy } from 'ramda'; import { useLabStore } from '~/store/lab/useLabStore'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { INode } from '~/types'; import { useAuth } from '~/hooks/auth/useAuth'; @@ -47,7 +47,7 @@ export const useGetLabNodes = () => { } ); - const nodes = uniqBy(n => n.node.id, flatten(data || [])); + const nodes = useMemo(() => uniqBy(n => n.node.id, flatten(data || [])), [data]); const hasMore = (data?.[size - 1]?.length || 0) >= 1; const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); diff --git a/src/hooks/messages/useMessages.ts b/src/hooks/messages/useMessages.ts index 1c94a99e..9b41ef8f 100644 --- a/src/hooks/messages/useMessages.ts +++ b/src/hooks/messages/useMessages.ts @@ -2,6 +2,7 @@ import useSWR from 'swr'; import { API } from '~/constants/api'; import { apiGetUserMessages } from '~/api/messages'; import { IMessage } from '~/types'; +import { useMemo } from 'react'; const getKey = (username: string): string | null => { return username ? `${API.USER.MESSAGES}/${username}` : null; @@ -11,7 +12,7 @@ export const useMessages = (username: string) => { apiGetUserMessages({ username }) ); - const messages: IMessage[] = data?.messages || []; + const messages: IMessage[] = useMemo(() => data?.messages || [], [data]); return { messages, isLoading: !data && isValidating }; }; diff --git a/src/hooks/search/useSearch.ts b/src/hooks/search/useSearch.ts index 72ec15f7..7f7486f7 100644 --- a/src/hooks/search/useSearch.ts +++ b/src/hooks/search/useSearch.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; import { flatten } from 'ramda'; import { getSearchResults } from '~/api/flow'; @@ -44,7 +44,7 @@ export const useSearch = () => { const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); const hasMore = (data?.[size - 1]?.length || 0) >= RESULTS_COUNT; - const results = flatten(data || []); + const results = useMemo(() => flatten(data || []), [data]); useEffect(() => { const timeout = setTimeout(async () => { diff --git a/src/hooks/tag/useTagAutocomplete.ts b/src/hooks/tag/useTagAutocomplete.ts index 3b66d1e8..bc8e10ab 100644 --- a/src/hooks/tag/useTagAutocomplete.ts +++ b/src/hooks/tag/useTagAutocomplete.ts @@ -1,7 +1,7 @@ import useSWR from 'swr'; import { API } from '~/constants/api'; import { apiGetTagSuggestions } from '~/api/tags'; -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; export const useTagAutocomplete = (input: string, exclude: string[]): string[] => { const [search, setSearch] = useState(''); @@ -19,5 +19,5 @@ export const useTagAutocomplete = (input: string, exclude: string[]): string[] = } ); - return data || []; + return useMemo(() => data || [], [data]); }; diff --git a/src/hooks/tag/useTagNodes.ts b/src/hooks/tag/useTagNodes.ts index 82ed398a..a6ba9a6a 100644 --- a/src/hooks/tag/useTagNodes.ts +++ b/src/hooks/tag/useTagNodes.ts @@ -2,7 +2,7 @@ import { INode } from '~/types'; import { API } from '~/constants/api'; import { flatten, isNil } from 'ramda'; import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { apiGetNodesOfTag } from '~/api/tags'; const PAGE_SIZE = 10; @@ -40,7 +40,7 @@ export const useTagNodes = (tag: string) => { } ); - const nodes = flatten(data || []); + const nodes = useMemo(() => flatten(data || []), [data]); const hasMore = (data?.[size - 1]?.length || 0) >= PAGE_SIZE; const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); diff --git a/src/layouts/FlowLayout/index.tsx b/src/layouts/FlowLayout/index.tsx index ed4d34e3..0e77a6ff 100644 --- a/src/layouts/FlowLayout/index.tsx +++ b/src/layouts/FlowLayout/index.tsx @@ -7,6 +7,7 @@ import classNames from 'classnames'; import { FlowSwiperHero } from '~/components/flow/FlowSwiperHero'; import { useFlowContext } from '~/utils/context/FlowContextProvider'; import { useUser } from '~/hooks/auth/useUser'; +import { useInfiniteLoader } from '~/hooks/dom/useInfiniteLoader'; interface Props { isFluid: boolean; @@ -14,9 +15,11 @@ interface Props { } const FlowLayout: FC = ({ isFluid, onToggleLayout }) => { - const { heroes, nodes, onChangeCellView } = useFlowContext(); + const { heroes, nodes, onChangeCellView, loadMore, isSyncing } = useFlowContext(); const { user } = useUser(); + useInfiniteLoader(loadMore, isSyncing); + return (
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 5a66404b..c0ff290e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -7,7 +7,17 @@ import { observer } from 'mobx-react-lite'; interface Props {} const FlowPage: FC = observer(() => { - const { updates, nodes, heroes, recent, isFluid, toggleLayout, onChangeCellView } = useFlow(); + const { + updates, + nodes, + heroes, + recent, + isFluid, + toggleLayout, + onChangeCellView, + loadMore, + isSyncing, + } = useFlow(); return ( = observer(() => { recent={recent} heroes={heroes} nodes={nodes} + loadMore={loadMore} + isSyncing={isSyncing} onChangeCellView={onChangeCellView} > diff --git a/src/utils/context/FlowContextProvider.tsx b/src/utils/context/FlowContextProvider.tsx index d7a56afa..0f35420e 100644 --- a/src/utils/context/FlowContextProvider.tsx +++ b/src/utils/context/FlowContextProvider.tsx @@ -6,6 +6,8 @@ export interface FlowContextProps { recent: IFlowNode[]; heroes: IFlowNode[]; nodes: IFlowNode[]; + isSyncing: boolean; + loadMore: () => Promise; onChangeCellView: (id: INode['id'], flow: FlowDisplay) => void; } @@ -14,6 +16,8 @@ export const FlowContext = createContext({ recent: [], heroes: [], nodes: [], + isSyncing: false, + loadMore: async () => {}, onChangeCellView: () => {}, });