From 603da0fa01b928919036b1e277cd5597791ead87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicole=20Miko=C5=82ajczyk?= Date: Sun, 1 Jun 2025 07:18:14 +0200 Subject: [PATCH] pl-fe: migrate events lists to tanstack query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicole Mikołajczyk --- packages/pl-fe/src/actions/events.ts | 67 +------------------ .../pl-fe/src/pages/status-lists/events.tsx | 18 ++--- .../queries/status-lists/use-events-lists.ts | 28 ++++++++ packages/pl-fe/src/reducers/status-lists.ts | 25 +------ 4 files changed, 35 insertions(+), 103 deletions(-) create mode 100644 packages/pl-fe/src/queries/status-lists/use-events-lists.ts diff --git a/packages/pl-fe/src/actions/events.ts b/packages/pl-fe/src/actions/events.ts index 4d122c802..b65b4c85f 100644 --- a/packages/pl-fe/src/actions/events.ts +++ b/packages/pl-fe/src/actions/events.ts @@ -6,7 +6,7 @@ import toast from 'pl-fe/toast'; import { importEntities } from './importer'; import { STATUS_FETCH_SOURCE_FAIL, STATUS_FETCH_SOURCE_REQUEST, STATUS_FETCH_SOURCE_SUCCESS } from './statuses'; -import type { CreateEventParams, Location, MediaAttachment, PaginatedResponse, Status } from 'pl-api'; +import type { CreateEventParams, Location, MediaAttachment, Status } from 'pl-api'; import type { AppDispatch, RootState } from 'pl-fe/store'; const EVENT_JOIN_REQUEST = 'EVENT_JOIN_REQUEST' as const; @@ -19,13 +19,6 @@ const EVENT_COMPOSE_CANCEL = 'EVENT_COMPOSE_CANCEL' as const; const EVENT_FORM_SET = 'EVENT_FORM_SET' as const; -const RECENT_EVENTS_FETCH_REQUEST = 'RECENT_EVENTS_FETCH_REQUEST' as const; -const RECENT_EVENTS_FETCH_SUCCESS = 'RECENT_EVENTS_FETCH_SUCCESS' as const; -const RECENT_EVENTS_FETCH_FAIL = 'RECENT_EVENTS_FETCH_FAIL' as const; -const JOINED_EVENTS_FETCH_REQUEST = 'JOINED_EVENTS_FETCH_REQUEST' as const; -const JOINED_EVENTS_FETCH_SUCCESS = 'JOINED_EVENTS_FETCH_SUCCESS' as const; -const JOINED_EVENTS_FETCH_FAIL = 'JOINED_EVENTS_FETCH_FAIL' as const; - const noOp = () => new Promise(f => f(undefined)); const messages = defineMessages({ @@ -190,61 +183,13 @@ const initEventEdit = (statusId: string) => (dispatch: AppDispatch, getState: () }); }; -const fetchRecentEvents = () => - (dispatch: AppDispatch, getState: () => RootState) => { - if (getState().status_lists.recent_events?.isLoading) { - return; - } - - dispatch({ type: RECENT_EVENTS_FETCH_REQUEST }); - - return getClient(getState()).timelines.publicTimeline({ - only_events: true, - }).then(response => { - dispatch(importEntities({ statuses: response.items })); - dispatch({ - type: RECENT_EVENTS_FETCH_SUCCESS, - statuses: response.items, - next: response.next, - }); - }).catch(error => { - dispatch({ type: RECENT_EVENTS_FETCH_FAIL, error }); - }); - }; - -const fetchJoinedEvents = () => - (dispatch: AppDispatch, getState: () => RootState) => { - if (getState().status_lists.joined_events?.isLoading) { - return; - } - - dispatch({ type: JOINED_EVENTS_FETCH_REQUEST }); - - getClient(getState).events.getJoinedEvents().then(response => { - dispatch(importEntities({ statuses: response.items })); - dispatch({ - type: JOINED_EVENTS_FETCH_SUCCESS, - statuses: response.items, - next: response.next, - }); - }).catch(error => { - dispatch({ type: JOINED_EVENTS_FETCH_FAIL, error }); - }); - }; - type EventsAction = | ReturnType | ReturnType | ReturnType | ReturnType | ReturnType - | EventFormSetAction - | { type: typeof RECENT_EVENTS_FETCH_REQUEST } - | { type: typeof RECENT_EVENTS_FETCH_SUCCESS; statuses: Array; next: (() => Promise>) | null } - | { type: typeof RECENT_EVENTS_FETCH_FAIL; error: unknown } - | { type: typeof JOINED_EVENTS_FETCH_REQUEST } - | { type: typeof JOINED_EVENTS_FETCH_SUCCESS; statuses: Array; next: (() => Promise>) | null } - | { type: typeof JOINED_EVENTS_FETCH_FAIL; error: unknown } + | EventFormSetAction; export { EVENT_JOIN_REQUEST, @@ -253,19 +198,11 @@ export { EVENT_LEAVE_FAIL, EVENT_COMPOSE_CANCEL, EVENT_FORM_SET, - RECENT_EVENTS_FETCH_REQUEST, - RECENT_EVENTS_FETCH_SUCCESS, - RECENT_EVENTS_FETCH_FAIL, - JOINED_EVENTS_FETCH_REQUEST, - JOINED_EVENTS_FETCH_SUCCESS, - JOINED_EVENTS_FETCH_FAIL, submitEvent, joinEvent, leaveEvent, fetchEventIcs, cancelEventCompose, initEventEdit, - fetchRecentEvents, - fetchJoinedEvents, type EventsAction, }; diff --git a/packages/pl-fe/src/pages/status-lists/events.tsx b/packages/pl-fe/src/pages/status-lists/events.tsx index 58caf8338..ff13ab28c 100644 --- a/packages/pl-fe/src/pages/status-lists/events.tsx +++ b/packages/pl-fe/src/pages/status-lists/events.tsx @@ -1,9 +1,8 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { Link } from 'react-router-dom'; import ReactSwipeableViews from 'react-swipeable-views'; -import { fetchJoinedEvents, fetchRecentEvents } from 'pl-fe/actions/events'; import EventPreview from 'pl-fe/components/event-preview'; import Button from 'pl-fe/components/ui/button'; import Card, { CardBody, CardHeader, CardTitle } from 'pl-fe/components/ui/card'; @@ -11,8 +10,8 @@ import Column from 'pl-fe/components/ui/column'; import HStack from 'pl-fe/components/ui/hstack'; import Icon from 'pl-fe/components/ui/icon'; import PlaceholderEventPreview from 'pl-fe/features/placeholder/components/placeholder-event-preview'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; +import { useJoinedEvents, useRecentEvents } from 'pl-fe/queries/status-lists/use-events-lists'; import { makeGetStatus } from 'pl-fe/selectors'; const messages = defineMessages({ @@ -91,17 +90,8 @@ const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMe const EventsPage = () => { const intl = useIntl(); - const dispatch = useAppDispatch(); - - const recentEvents = useAppSelector((state) => state.status_lists.recent_events!.items); - const recentEventsLoading = useAppSelector((state) => state.status_lists.recent_events!.isLoading); - const joinedEvents = useAppSelector((state) => state.status_lists.joined_events!.items); - const joinedEventsLoading = useAppSelector((state) => state.status_lists.joined_events!.isLoading); - - useEffect(() => { - dispatch(fetchRecentEvents()); - dispatch(fetchJoinedEvents()); - }, []); + const { data: recentEvents = [], isLoading: recentEventsLoading } = useRecentEvents(); + const { data: joinedEvents = [], isLoading: joinedEventsLoading } = useJoinedEvents(); return ( diff --git a/packages/pl-fe/src/queries/status-lists/use-events-lists.ts b/packages/pl-fe/src/queries/status-lists/use-events-lists.ts new file mode 100644 index 000000000..9356936e8 --- /dev/null +++ b/packages/pl-fe/src/queries/status-lists/use-events-lists.ts @@ -0,0 +1,28 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; + +import { makePaginatedResponseQueryOptions } from '../utils/make-paginated-response-query-options'; +import { minifyStatusList } from '../utils/minify-list'; + +const recentEventsQueryOptions = makePaginatedResponseQueryOptions( + () => ['statusLists', 'recentEvents'], + (client) => client.timelines.publicTimeline({ + only_events: true, + }).then(minifyStatusList), +)(); + +const useRecentEvents = () => useInfiniteQuery({ + ...recentEventsQueryOptions, + staleTime: 5 * 60 * 1000, // 5 minutes +}); + +const joinedEventsQueryOptions = makePaginatedResponseQueryOptions( + () => ['statusLists', 'joinedEvents'], + (client) => client.events.getJoinedEvents().then(minifyStatusList), +)(); + +const useJoinedEvents = () => useInfiniteQuery({ + ...joinedEventsQueryOptions, + staleTime: 5 * 60 * 1000, // 5 minutes +}); + +export { useRecentEvents, useJoinedEvents }; diff --git a/packages/pl-fe/src/reducers/status-lists.ts b/packages/pl-fe/src/reducers/status-lists.ts index ea2c59fbb..50740c8f0 100644 --- a/packages/pl-fe/src/reducers/status-lists.ts +++ b/packages/pl-fe/src/reducers/status-lists.ts @@ -9,15 +9,6 @@ import { BOOKMARKED_STATUSES_EXPAND_FAIL, type BookmarksAction, } from 'pl-fe/actions/bookmarks'; -import { - RECENT_EVENTS_FETCH_REQUEST, - RECENT_EVENTS_FETCH_SUCCESS, - RECENT_EVENTS_FETCH_FAIL, - JOINED_EVENTS_FETCH_REQUEST, - JOINED_EVENTS_FETCH_SUCCESS, - JOINED_EVENTS_FETCH_FAIL, - type EventsAction, -} from 'pl-fe/actions/events'; import { FAVOURITED_STATUSES_FETCH_REQUEST, FAVOURITED_STATUSES_FETCH_SUCCESS, @@ -65,8 +56,6 @@ const initialState: State = { favourites: newStatusList(), bookmarks: newStatusList(), pins: newStatusList(), - recent_events: newStatusList(), - joined_events: newStatusList(), }; const getStatusId = (status: string | Pick) => typeof status === 'string' ? status : status.id; @@ -127,7 +116,7 @@ const removeBookmarkFromLists = (state: State, status: Pick { +const statusLists = (state = initialState, action: BookmarksAction | FavouritesAction | InteractionsAction | PinStatusesAction | StatusesAction): State => { switch (action.type) { case FAVOURITED_STATUSES_FETCH_REQUEST: case FAVOURITED_STATUSES_EXPAND_REQUEST: @@ -169,18 +158,6 @@ const statusLists = (state = initialState, action: BookmarksAction | EventsActio return create(state, draft => prependOneToList(draft, 'pins', action.status)); case UNPIN_SUCCESS: return create(state, draft => removeOneFromList(draft, 'pins', action.status)); - case RECENT_EVENTS_FETCH_REQUEST: - return create(state, draft => setLoading(draft, 'recent_events', true)); - case RECENT_EVENTS_FETCH_FAIL: - return create(state, draft => setLoading(draft, 'recent_events', false)); - case RECENT_EVENTS_FETCH_SUCCESS: - return create(state, draft => normalizeList(draft, 'recent_events', action.statuses, action.next)); - case JOINED_EVENTS_FETCH_REQUEST: - return create(state, draft => setLoading(draft, 'joined_events', true)); - case JOINED_EVENTS_FETCH_FAIL: - return create(state, draft => setLoading(draft, 'joined_events', false)); - case JOINED_EVENTS_FETCH_SUCCESS: - return create(state, draft => normalizeList(draft, 'joined_events', action.statuses, action.next)); default: return state; }