Skip to content

Commit 9798be6

Browse files
authored
Update Docker builds (#85)
* Update to Next 15 * Fix CI/CD compatibility with React 19 and Next.js 15 - Add --legacy-peer-deps flag to GitHub workflow npm ci commands to resolve React 19 peer dependency conflicts - Update react-image-gallery to 1.4.0 for React 19 compatibility - Fix AutocompleteSearch Configure component to remove TypeScript any usage - Remove deprecated yarn.lock file in favor of package-lock.json This resolves the ERESOLVE peer dependency errors preventing successful CI/CD builds. * Remove yarn.lock as project now uses npm exclusively * Upgrade to TanStack Query v5 for React 19 compatibility - Replace react-query@3.39.3 with @tanstack/react-query@5.85.5 - Update all query hooks to use new TanStack Query v5 API (queryKey/queryFn object format) - Replace Hydrate with HydrationBoundary component - Add initialPageParam to useInfiniteQuery for v5 compatibility - Document that --legacy-peer-deps is only needed for react-select-search This is the idiomatic solution for React 19 compatibility, replacing the deprecated react-query package with the modern, actively maintained TanStack Query. * Replace react-select-search with react-select for full React 19 compatibility - Remove react-select-search@4.1.6 (React 18 only) and install react-select@5.10.2 - Upgrade react-share@5.1.0 → 5.2.2 for React 19 support - Update MobileFilter component to use react-select API with proper TypeScript types - Remove --legacy-peer-deps flag from GitHub workflow - no longer needed - Add dark theme styling for react-select to match existing UI This completes the idiomatic React 19 upgrade by replacing all incompatible packages with modern alternatives. * Regenerate package-lock.json to remove old react-query references This ensures Docker builds use the clean dependency tree with @tanstack/react-query instead of the deprecated react-query package.
1 parent faf9505 commit 9798be6

15 files changed

Lines changed: 9716 additions & 10094 deletions

File tree

components/blog/queries/articles.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type QueryClient, useQuery } from 'react-query';
1+
import { type QueryClient, useQuery } from '@tanstack/react-query';
22
import { type APIResponseType, type Article } from 'utils/types';
33
import { APIPaths, getApiURL } from 'utils/urls';
44

@@ -17,10 +17,10 @@ export const ARTICLES_PREFETCH_KEY = 'articles';
1717
* @see https://react-query.tanstack.com/guides/prefetching#_top
1818
*/
1919
export async function prefetchArticles(queryClient: QueryClient) {
20-
return await queryClient.prefetchQuery(
21-
ARTICLES_PREFETCH_KEY,
22-
fetchArticles,
23-
);
20+
return await queryClient.prefetchQuery({
21+
queryKey: [ARTICLES_PREFETCH_KEY],
22+
queryFn: fetchArticles,
23+
});
2424
}
2525

2626
/**
@@ -29,7 +29,10 @@ export async function prefetchArticles(queryClient: QueryClient) {
2929
* @see https://react-query.tanstack.com/guides/queries
3030
*/
3131
export function useArticlesQuery() {
32-
return useQuery(ARTICLES_PREFETCH_KEY, fetchArticles);
32+
return useQuery({
33+
queryKey: [ARTICLES_PREFETCH_KEY],
34+
queryFn: fetchArticles,
35+
});
3336
}
3437

3538
/**
@@ -38,7 +41,9 @@ export function useArticlesQuery() {
3841
* @see https://react-query.tanstack.com/guides/queries
3942
*/
4043
export function useArticleQueryCount() {
41-
return useQuery(ARTICLES_PREFETCH_KEY, fetchArticles, {
44+
return useQuery({
45+
queryKey: [ARTICLES_PREFETCH_KEY],
46+
queryFn: fetchArticles,
4247
select: ({ data }) => data.length,
4348
});
4449
}

components/homepage/queries/mostViewed.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QueryClient, useQuery } from 'react-query';
1+
import { QueryClient, useQuery } from '@tanstack/react-query';
22
import { APIPaths, getApiURL } from 'utils/urls';
33
import { type Tool } from '@components/tools';
44
import { type APIResponseType } from 'utils/types';
@@ -18,10 +18,10 @@ export const MOST_VIEWED_PREFETCH_KEY = 'mostViewed';
1818
* @see https://react-query.tanstack.com/guides/prefetching#_top
1919
*/
2020
export async function prefetchMostViewed(queryClient: QueryClient) {
21-
return await queryClient.prefetchQuery(
22-
MOST_VIEWED_PREFETCH_KEY,
23-
fetchMostViewed,
24-
);
21+
return await queryClient.prefetchQuery({
22+
queryKey: [MOST_VIEWED_PREFETCH_KEY],
23+
queryFn: fetchMostViewed,
24+
});
2525
}
2626

2727
/**
@@ -30,7 +30,10 @@ export async function prefetchMostViewed(queryClient: QueryClient) {
3030
* @see https://react-query.tanstack.com/guides/queries
3131
*/
3232
export function useMostViewedQuery() {
33-
return useQuery(MOST_VIEWED_PREFETCH_KEY, fetchMostViewed);
33+
return useQuery({
34+
queryKey: [MOST_VIEWED_PREFETCH_KEY],
35+
queryFn: fetchMostViewed,
36+
});
3437
}
3538

3639
/**
@@ -39,7 +42,9 @@ export function useMostViewedQuery() {
3942
* @see https://react-query.tanstack.com/guides/queries
4043
*/
4144
export function useMostViewedQueryCount() {
42-
return useQuery(MOST_VIEWED_PREFETCH_KEY, fetchMostViewed, {
45+
return useQuery({
46+
queryKey: [MOST_VIEWED_PREFETCH_KEY],
47+
queryFn: fetchMostViewed,
4348
select: ({ data }) => data.length,
4449
});
4550
}

components/homepage/queries/popularLanguages.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type QueryClient, useQuery } from 'react-query';
1+
import { type QueryClient, useQuery } from '@tanstack/react-query';
22
import { APIPaths, getApiURL } from 'utils/urls';
33
import { type ToolsByLanguage } from '@components/tools';
44
import { type APIResponseType } from 'utils/types';
@@ -18,10 +18,10 @@ export const POPULAR_LANGUAGES_PREFETCH_KEY = 'popularLanguages';
1818
* @see https://react-query.tanstack.com/guides/prefetching#_top
1919
*/
2020
export async function prefetchPopularLanguages(queryClient: QueryClient) {
21-
return await queryClient.prefetchQuery(
22-
POPULAR_LANGUAGES_PREFETCH_KEY,
23-
fetchPopularLanguages,
24-
);
21+
return await queryClient.prefetchQuery({
22+
queryKey: [POPULAR_LANGUAGES_PREFETCH_KEY],
23+
queryFn: fetchPopularLanguages,
24+
});
2525
}
2626

2727
/**
@@ -30,7 +30,10 @@ export async function prefetchPopularLanguages(queryClient: QueryClient) {
3030
* @see https://react-query.tanstack.com/guides/queries
3131
*/
3232
export function usePopularLanguagesQuery() {
33-
return useQuery(POPULAR_LANGUAGES_PREFETCH_KEY, fetchPopularLanguages);
33+
return useQuery({
34+
queryKey: [POPULAR_LANGUAGES_PREFETCH_KEY],
35+
queryFn: fetchPopularLanguages,
36+
});
3437
}
3538

3639
/**
@@ -39,7 +42,9 @@ export function usePopularLanguagesQuery() {
3942
* @see https://react-query.tanstack.com/guides/queries
4043
*/
4144
export function usePopularLanguagesQueryCount() {
42-
return useQuery(POPULAR_LANGUAGES_PREFETCH_KEY, fetchPopularLanguages, {
45+
return useQuery({
46+
queryKey: [POPULAR_LANGUAGES_PREFETCH_KEY],
47+
queryFn: fetchPopularLanguages,
4348
select: ({ data }) => Object.keys(data).length,
4449
});
4550
}

components/tools/listPage/ListPageComponent/ListPageComponent.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { MobileFilters, Tool, ToolCard, ToolsSidebar } from '@components/tools';
99
import { useSearchState } from 'context/SearchProvider';
1010
import { useRouterPush } from 'hooks';
1111
import { FC, useCallback, useEffect, useRef } from 'react';
12-
import { useInfiniteQuery } from 'react-query';
12+
import { useInfiniteQuery } from '@tanstack/react-query';
1313
import { objectToQueryString } from 'utils/query';
1414
import { type ArticlePreview } from 'utils/types';
1515
import { FilterOption } from '../ToolsSidebar/FilterCard/FilterCard';
@@ -55,6 +55,7 @@ const ListComponent: FC<ListComponentProps> = ({
5555
} = useInfiniteQuery({
5656
queryKey: ['paginated-tools'],
5757
queryFn: fetchTools,
58+
initialPageParam: 0,
5859
getNextPageParam: (lastPage) => lastPage.nextCursor,
5960
});
6061

components/tools/listPage/MobileFilters/MobileFilter/MobileFilter.tsx

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
import { FC } from 'react';
22
import styles from './MobileFilter.module.css';
3-
import 'react-select-search/style.css';
4-
import SelectSearch, {
5-
SelectedOptionValue,
6-
SelectSearchOption,
7-
} from 'react-select-search';
3+
import Select, { MultiValue } from 'react-select';
84
import { Button, PanelHeader } from '@components/elements';
95
import classNames from 'classnames';
106
import { SearchState, SearchFilter } from 'context/SearchProvider';
117

8+
interface Option {
9+
value: string;
10+
label: string;
11+
}
12+
13+
interface InputOption {
14+
value: string;
15+
name: string;
16+
}
17+
1218
export interface MobileFilterProps {
1319
id: string;
1420
label: string;
15-
options: SelectSearchOption[];
21+
options: InputOption[];
1622
placeholder: string;
1723
state: SearchState;
1824
setState: (state: SearchState) => void;
@@ -28,9 +34,13 @@ const MobileFilter: FC<MobileFilterProps> = ({
2834
setState,
2935
topList,
3036
}) => {
31-
const onChange = (value: SelectedOptionValue | SelectedOptionValue[]) => {
32-
const newValue = Array.isArray(value) ? value : [value];
33-
setState({ ...state, [id as SearchFilter]: newValue });
37+
const selectOptions: Option[] = options.map((opt) => ({
38+
value: opt.value,
39+
label: opt.name,
40+
}));
41+
const onChange = (selectedOptions: MultiValue<Option>) => {
42+
const values = selectedOptions.map((option) => option.value);
43+
setState({ ...state, [id as SearchFilter]: values });
3444
};
3545

3646
const clear = () => {
@@ -47,13 +57,43 @@ const MobileFilter: FC<MobileFilterProps> = ({
4757
Clear
4858
</Button>
4959
</PanelHeader>
50-
<SelectSearch
51-
options={options}
52-
value={state[id as SearchFilter] || ''}
53-
id={id}
54-
search={true}
60+
<Select
61+
options={selectOptions}
62+
value={selectOptions.filter((option) =>
63+
(state[id as SearchFilter] || []).includes(option.value),
64+
)}
65+
isMulti
66+
isSearchable
5567
onChange={onChange}
5668
placeholder={placeholder}
69+
styles={{
70+
control: (base) => ({
71+
...base,
72+
backgroundColor: '#0a1a29',
73+
borderColor: '#486a8b',
74+
color: '#ffffff',
75+
fontSize: '16px',
76+
}),
77+
menu: (base) => ({
78+
...base,
79+
backgroundColor: '#0a1a29',
80+
}),
81+
option: (base, state) => ({
82+
...base,
83+
backgroundColor: state.isFocused
84+
? '#486a8b'
85+
: '#0a1a29',
86+
color: '#ffffff',
87+
}),
88+
multiValue: (base) => ({
89+
...base,
90+
backgroundColor: '#486a8b',
91+
}),
92+
multiValueLabel: (base) => ({
93+
...base,
94+
color: '#ffffff',
95+
}),
96+
}}
5797
/>
5898
</div>
5999
);

components/tools/listPage/MobileFilters/MobileFilters.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { FC, useState } from 'react';
22
import classNames from 'classnames';
33
import { Button, PanelHeader } from '@components/elements';
44
import styles from './MobileFilters.module.css';
5-
import 'react-select-search/style.css';
65
import { useLanguagesQuery } from '@components/tools/queries';
76
import { useSearchState } from 'context/SearchProvider';
87
import MobileFilter from './MobileFilter/MobileFilter';

components/tools/queries/languages.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type QueryClient, useQuery } from 'react-query';
1+
import { type QueryClient, useQuery } from '@tanstack/react-query';
22
import { type APIResponseType, type ApiTag } from 'utils/types';
33
import { APIPaths, getApiURL } from 'utils/urls';
44

@@ -17,10 +17,10 @@ export const LANGUAGES_PREFETCH_KEY = 'languages';
1717
* @see https://react-query.tanstack.com/guides/prefetching#_top
1818
*/
1919
export async function prefetchLanguages(queryClient: QueryClient) {
20-
return await queryClient.prefetchQuery(
21-
LANGUAGES_PREFETCH_KEY,
22-
fetchLanguages,
23-
);
20+
return await queryClient.prefetchQuery({
21+
queryKey: [LANGUAGES_PREFETCH_KEY],
22+
queryFn: fetchLanguages,
23+
});
2424
}
2525

2626
/**
@@ -29,7 +29,10 @@ export async function prefetchLanguages(queryClient: QueryClient) {
2929
* @see https://react-query.tanstack.com/guides/queries
3030
*/
3131
export function useLanguagesQuery() {
32-
return useQuery(LANGUAGES_PREFETCH_KEY, fetchLanguages);
32+
return useQuery({
33+
queryKey: [LANGUAGES_PREFETCH_KEY],
34+
queryFn: fetchLanguages,
35+
});
3336
}
3437

3538
/**
@@ -38,7 +41,9 @@ export function useLanguagesQuery() {
3841
* @see https://react-query.tanstack.com/guides/queries
3942
*/
4043
export function useLanguageQueryCount() {
41-
return useQuery(LANGUAGES_PREFETCH_KEY, fetchLanguages, {
44+
return useQuery({
45+
queryKey: [LANGUAGES_PREFETCH_KEY],
46+
queryFn: fetchLanguages,
4247
select: ({ data }) => data.length,
4348
});
4449
}

components/tools/queries/others.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type QueryClient, useQuery } from 'react-query';
1+
import { type QueryClient, useQuery } from '@tanstack/react-query';
22
import { type APIResponseType, type ApiTag } from 'utils/types';
33
import { APIPaths, getApiURL } from 'utils/urls';
44

@@ -17,7 +17,10 @@ export const OTHERS_PREFETCH_KEY = 'others';
1717
* @see https://react-query.tanstack.com/guides/prefetching#_top
1818
*/
1919
export async function prefetchOthers(queryClient: QueryClient) {
20-
return await queryClient.prefetchQuery(OTHERS_PREFETCH_KEY, fetchOthers);
20+
return await queryClient.prefetchQuery({
21+
queryKey: [OTHERS_PREFETCH_KEY],
22+
queryFn: fetchOthers,
23+
});
2124
}
2225

2326
/**
@@ -26,7 +29,10 @@ export async function prefetchOthers(queryClient: QueryClient) {
2629
* @see https://react-query.tanstack.com/guides/queries
2730
*/
2831
export function useOthersQuery() {
29-
return useQuery(OTHERS_PREFETCH_KEY, fetchOthers);
32+
return useQuery({
33+
queryKey: [OTHERS_PREFETCH_KEY],
34+
queryFn: fetchOthers,
35+
});
3036
}
3137

3238
/**
@@ -35,7 +41,9 @@ export function useOthersQuery() {
3541
* @see https://react-query.tanstack.com/guides/queries
3642
*/
3743
export function useOtherQueryCount() {
38-
return useQuery(OTHERS_PREFETCH_KEY, fetchOthers, {
44+
return useQuery({
45+
queryKey: [OTHERS_PREFETCH_KEY],
46+
queryFn: fetchOthers,
3947
select: ({ data }) => data.length,
4048
});
4149
}

components/tools/queries/tool.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QueryClient, useQuery } from 'react-query';
1+
import { QueryClient, useQuery } from '@tanstack/react-query';
22
import { APIPaths, getApiURL } from 'utils/urls';
33
import { Tool } from '../types';
44
import { type APIResponseType } from 'utils/types';
@@ -12,9 +12,10 @@ import { type APIResponseType } from 'utils/types';
1212
* @see https://react-query.tanstack.com/guides/prefetching#_top
1313
*/
1414
export async function prefetchTool(queryClient: QueryClient, slug: string) {
15-
return await queryClient.prefetchQuery(`tool-${slug}`, () =>
16-
fetchToolData(slug),
17-
);
15+
return await queryClient.prefetchQuery({
16+
queryKey: [`tool-${slug}`],
17+
queryFn: () => fetchToolData(slug),
18+
});
1819
}
1920

2021
/**
@@ -23,7 +24,10 @@ export async function prefetchTool(queryClient: QueryClient, slug: string) {
2324
* @see https://react-query.tanstack.com/guides/queries
2425
*/
2526
export function useToolQuery(slug: string) {
26-
return useQuery(`tool-${slug}`, () => fetchToolData(slug));
27+
return useQuery({
28+
queryKey: [`tool-${slug}`],
29+
queryFn: () => fetchToolData(slug),
30+
});
2731
}
2832

2933
/**

0 commit comments

Comments
 (0)