replace zustand with @tanstack/react-query

This commit is contained in:
vchikalkin 2025-01-15 14:37:58 +03:00
parent 59e9d61e37
commit 4af2ae4d4e
9 changed files with 82 additions and 74 deletions

View File

@ -1,4 +1,4 @@
import { TelegramProvider } from '@/providers';
import { TelegramProvider } from '@/providers/telegram';
import { type PropsWithChildren } from 'react';
export default async function Layout({ children }: Readonly<PropsWithChildren>) {

View File

@ -1,4 +1,5 @@
import { AuthProvider } from '@/providers';
import { AuthProvider } from '@/providers/auth';
import { QueryProvider } from '@/providers/query';
import { ThemeProvider } from '@/providers/theme-provider';
import { I18nProvider } from '@/utils/i18n/provider';
import '@repo/ui/globals.css';
@ -18,7 +19,9 @@ export default async function RootLayout({ children }: Readonly<PropsWithChildre
<body className="bg-secondary">
<I18nProvider>
<ThemeProvider>
<AuthProvider>{children}</AuthProvider>
<AuthProvider>
<QueryProvider>{children}</QueryProvider>
</AuthProvider>
</ThemeProvider>
</I18nProvider>
</body>

View File

@ -1,26 +1,26 @@
/* eslint-disable promise/prefer-await-to-then */
'use client';
import { getClients, getMasters } from '@/actions/contacts';
import { ContactsFilterContext } from '@/context/contacts-filter';
import { useBoundStore } from '@/store';
import { useQuery } from '@tanstack/react-query';
import { sift } from 'radash';
import { use, useEffect, useMemo } from 'react';
import { use, useMemo } from 'react';
export function useCustomerContacts() {
const { filter } = use(ContactsFilterContext);
const { clients, masters, setClients, setMasters } = useBoundStore();
useEffect(() => {
if ((filter === 'masters' || filter === 'all') && !masters)
getMasters().then((response) => {
if (response?.masters) setMasters(response.masters);
});
const { data: clientsData } = useQuery({
queryFn: getClients,
queryKey: ['contacts', 'clients'],
});
if ((filter === 'clients' || filter === 'all') && !clients)
getClients().then((response) => {
if (response?.clients) setClients(response.clients);
});
}, [filter]);
const clients = clientsData?.clients;
const { data: mastersData } = useQuery({
queryFn: getMasters,
queryKey: ['contacts', 'masters'],
});
const masters = mastersData?.masters;
const contacts = useMemo(() => {
switch (filter) {

View File

@ -15,6 +15,7 @@
},
"dependencies": {
"@repo/ui": "workspace:*",
"@tanstack/react-query": "^5.64.1",
"@telegram-apps/sdk-react": "^2.0.19",
"graphql": "catalog:",
"lucide-react": "catalog:",
@ -26,8 +27,7 @@
"react": "catalog:",
"react-dom": "catalog:",
"use-debounce": "^10.0.4",
"zod": "catalog:",
"zustand": "^5.0.3"
"zod": "catalog:"
},
"devDependencies": {
"@playwright/test": "^1.49.1",

View File

@ -1,2 +0,0 @@
export * from './auth';
export * from './telegram';

View File

@ -0,0 +1,42 @@
'use client';
// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top
import { isServer, QueryClient, QueryClientProvider } from '@tanstack/react-query';
function makeQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
staleTime: 60 * 1_000,
},
},
});
}
let browserQueryClient: QueryClient | undefined;
export function QueryProvider({ children }: { readonly children: React.ReactNode }) {
// NOTE: Avoid useState when initializing the query client if you don't
// have a suspense boundary between this and the code that may
// suspend because React will throw away the client on the initial
// render if it suspends and there is no boundary
const queryClient = getQueryClient();
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}
function getQueryClient() {
if (isServer) {
// Server: always make a new query client
return makeQueryClient();
} else {
// Browser: make a new query client if we don't already have one
// This is very important, so we don't re-make a new client if React
// suspends during the initial render. This may not be needed if we
// have a suspense boundary BELOW the creation of the query client
if (!browserQueryClient) browserQueryClient = makeQueryClient();
return browserQueryClient;
}
}

View File

@ -1,21 +0,0 @@
import type * as GQL from '@repo/graphql/types';
import { type StateCreator } from 'zustand';
export type ContactsStore = {
clients: Clients | null;
masters: Masters | null;
setClients: (clients: Clients) => void;
setMasters: (masters: Masters) => void;
};
type Clients = NonNullable<GQL.GetCustomerClientsQuery['customers'][0]>['clients'];
type Masters = NonNullable<GQL.GetCustomerMastersQuery['customers'][0]>['masters'];
export const createContactsSlice: StateCreator<ContactsStore> = (set) => {
return {
clients: null,
masters: null,
setClients: (clients) => set({ clients }),
setMasters: (masters) => set({ masters }),
};
};

View File

@ -1,6 +0,0 @@
import { type ContactsStore, createContactsSlice } from './contacts';
import { create } from 'zustand';
type Store = ContactsStore;
export const useBoundStore = create<Store>()((...a) => ({ ...createContactsSlice(...a) }));

44
pnpm-lock.yaml generated
View File

@ -141,6 +141,9 @@ importers:
'@repo/ui':
specifier: workspace:*
version: link:../../packages/ui
'@tanstack/react-query':
specifier: ^5.64.1
version: 5.64.1(react@19.0.0)
'@telegram-apps/sdk-react':
specifier: ^2.0.19
version: 2.0.19(@types/react@19.0.1)(react@19.0.0)
@ -177,9 +180,6 @@ importers:
zod:
specifier: 'catalog:'
version: 3.24.1
zustand:
specifier: ^5.0.3
version: 5.0.3(@types/react@19.0.1)(react@19.0.0)
devDependencies:
'@playwright/test':
specifier: ^1.49.1
@ -2440,6 +2440,14 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
'@tanstack/query-core@5.64.1':
resolution: {integrity: sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==}
'@tanstack/react-query@5.64.1':
resolution: {integrity: sha512-vW5ggHpIO2Yjj44b4sB+Fd3cdnlMJppXRBJkEHvld6FXh3j5dwWJoQo7mGtKI2RbSFyiyu/PhGAy0+Vv5ev9Eg==}
peerDependencies:
react: ^18 || ^19
'@telegraf/types@7.1.0':
resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==}
@ -6308,24 +6316,6 @@ packages:
zod@3.24.1:
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
zustand@5.0.3:
resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=18.0.0'
immer: '>=9.0.6'
react: '>=18.0.0'
use-sync-external-store: '>=1.2.0'
peerDependenciesMeta:
'@types/react':
optional: true
immer:
optional: true
react:
optional: true
use-sync-external-store:
optional: true
snapshots:
'@alloc/quick-lru@5.2.0': {}
@ -8709,6 +8699,13 @@ snapshots:
dependencies:
tslib: 2.8.1
'@tanstack/query-core@5.64.1': {}
'@tanstack/react-query@5.64.1(react@19.0.0)':
dependencies:
'@tanstack/query-core': 5.64.1
react: 19.0.0
'@telegraf/types@7.1.0': {}
'@telegram-apps/bridge@1.7.1':
@ -13080,8 +13077,3 @@ snapshots:
zen-observable@0.8.15: {}
zod@3.24.1: {}
zustand@5.0.3(@types/react@19.0.1)(react@19.0.0):
optionalDependencies:
'@types/react': 19.0.1
react: 19.0.0