mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 23:15:46 +01:00
✨ Add cache and stale timers for most react query
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { Autocomplete, createStyles, Flex, Tabs, TextInput } from '@mantine/core';
|
import { Autocomplete, createStyles, Flex, Tabs } from '@mantine/core';
|
||||||
import { UseFormReturnType } from '@mantine/form';
|
import { UseFormReturnType } from '@mantine/form';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const AppPing = ({ app }: AppPingProps) => {
|
|||||||
(config?.settings.customization.layout.enabledPing && app.network.enabledStatusChecker) ??
|
(config?.settings.customization.layout.enabledPing && app.network.enabledStatusChecker) ??
|
||||||
false;
|
false;
|
||||||
const { data, isLoading } = useQuery({
|
const { data, isLoading } = useQuery({
|
||||||
queryKey: [`ping/${app.id}`],
|
queryKey: ['ping', { id: app.id, name: app.name }],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response = await fetch(`/api/modules/ping?url=${encodeURI(app.url)}`);
|
const response = await fetch(`/api/modules/ping?url=${encodeURI(app.url)}`);
|
||||||
const isOk = app.network.okStatus.includes(response.status);
|
const isOk = app.network.okStatus.includes(response.status);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Box, createStyles, Group, Header as MantineHeader, Indicator } from '@mantine/core';
|
import { Box, createStyles, Group, Header as MantineHeader, Indicator } from '@mantine/core';
|
||||||
import { useEffect, useState } from 'react';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { CURRENT_VERSION, REPO_URL } from '../../../../data/constants';
|
import { CURRENT_VERSION, REPO_URL } from '../../../../data/constants';
|
||||||
import { useConfigContext } from '../../../config/provider';
|
|
||||||
import { Logo } from '../Logo';
|
import { Logo } from '../Logo';
|
||||||
import { useCardStyles } from '../useCardStyles';
|
import { useCardStyles } from '../useCardStyles';
|
||||||
import DockerMenuButton from '../../../modules/Docker/DockerModule';
|
import DockerMenuButton from '../../../modules/Docker/DockerModule';
|
||||||
@@ -14,20 +13,14 @@ export const HeaderHeight = 64;
|
|||||||
export function Header(props: any) {
|
export function Header(props: any) {
|
||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
const { classes: cardClasses } = useCardStyles(false);
|
const { classes: cardClasses } = useCardStyles(false);
|
||||||
|
const { isLoading, error, data } = useQuery({
|
||||||
const { config } = useConfigContext();
|
queryKey: ['github/latest'],
|
||||||
|
cacheTime: 1000 * 60 * 60 * 24,
|
||||||
const [newVersionAvailable, setNewVersionAvailable] = useState<string>('');
|
staleTime: 1000 * 60 * 60 * 5,
|
||||||
useEffect(() => {
|
queryFn: () =>
|
||||||
// Fetch Data here when component first mounted
|
fetch(`https://api.github.com/repos/${REPO_URL}/releases/latest`).then((res) => res.json()),
|
||||||
fetch(`https://api.github.com/repos/${REPO_URL}/releases/latest`).then((res) => {
|
});
|
||||||
res.json().then((data) => {
|
const newVersionAvailable = data?.tag_name !== CURRENT_VERSION ? data?.tag_name : undefined;
|
||||||
if (data.tag_name > CURRENT_VERSION) {
|
|
||||||
setNewVersionAvailable(data.tag_name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, [CURRENT_VERSION]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MantineHeader height={HeaderHeight} className={cardClasses.card}>
|
<MantineHeader height={HeaderHeight} className={cardClasses.card}>
|
||||||
@@ -39,7 +32,13 @@ export function Header(props: any) {
|
|||||||
<Search />
|
<Search />
|
||||||
<ToggleEditModeAction />
|
<ToggleEditModeAction />
|
||||||
<DockerMenuButton />
|
<DockerMenuButton />
|
||||||
<Indicator size={15} color="blue" withBorder processing disabled={!newVersionAvailable}>
|
<Indicator
|
||||||
|
size={15}
|
||||||
|
color="blue"
|
||||||
|
withBorder
|
||||||
|
processing
|
||||||
|
disabled={newVersionAvailable === undefined}
|
||||||
|
>
|
||||||
<SettingsMenu newVersionAvailable={newVersionAvailable} />
|
<SettingsMenu newVersionAvailable={newVersionAvailable} />
|
||||||
</Indicator>
|
</Indicator>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -148,13 +148,14 @@ export function Search() {
|
|||||||
} = useQuery(
|
} = useQuery(
|
||||||
['overseerr', debounced],
|
['overseerr', debounced],
|
||||||
async () => {
|
async () => {
|
||||||
if (debounced !== '' && selectedSearchEngine.value === 'overseerr' && debounced.length > 3) {
|
const res = await axios.get(`/api/modules/overseerr?query=${debounced}`);
|
||||||
const res = await axios.get(`/api/modules/overseerr?query=${debounced}`);
|
return res.data.results ?? [];
|
||||||
return res.data.results ?? [];
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
enabled:
|
||||||
|
isOverseerrEnabled === true &&
|
||||||
|
selectedSearchEngine.value === 'overseerr' &&
|
||||||
|
debounced.length > 3,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
refetchOnMount: false,
|
refetchOnMount: false,
|
||||||
refetchInterval: false,
|
refetchInterval: false,
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
import { QueryClient } from '@tanstack/react-query';
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
export const queryClient = new QueryClient();
|
export const queryClient = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
staleTime: 5 * 60 * 1000, // 5 mins
|
||||||
|
cacheTime: 10 * 60 * 1000, // 10 mins
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ function CalendarTile({ widget }: CalendarTileProps) {
|
|||||||
|
|
||||||
const { data: medias } = useQuery({
|
const { data: medias } = useQuery({
|
||||||
queryKey: ['calendar/medias', { month: month.getMonth(), year: month.getFullYear() }],
|
queryKey: ['calendar/medias', { month: month.getMonth(), year: month.getFullYear() }],
|
||||||
|
staleTime: 1000 * 60 * 60 * 5,
|
||||||
queryFn: async () =>
|
queryFn: async () =>
|
||||||
(await (
|
(await (
|
||||||
await fetch(
|
await fetch(
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function WeatherTile({ widget }: WeatherTileProps) {
|
|||||||
align="center"
|
align="center"
|
||||||
style={{ height: '100%', width: '100%' }}
|
style={{ height: '100%', width: '100%' }}
|
||||||
>
|
>
|
||||||
<Group align={'center'} position="center" spacing="xs">
|
<Group align="center" position="center" spacing="xs">
|
||||||
<WeatherIcon code={weather!.current_weather.weathercode} />
|
<WeatherIcon code={weather!.current_weather.weathercode} />
|
||||||
<Title>
|
<Title>
|
||||||
{getPerferedUnit(
|
{getPerferedUnit(
|
||||||
|
|||||||
@@ -11,12 +11,18 @@ export const useWeatherForCity = (cityName: string) => {
|
|||||||
data: city,
|
data: city,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
} = useQuery({ queryKey: ['weatherCity', { cityName }], queryFn: () => fetchCity(cityName) });
|
} = useQuery({
|
||||||
|
queryKey: ['weatherCity', { cityName }],
|
||||||
|
queryFn: () => fetchCity(cityName),
|
||||||
|
cacheTime: 1000 * 60 * 60 * 24, // the city is cached for 24 hours
|
||||||
|
staleTime: Infinity, // the city is never considered stale
|
||||||
|
});
|
||||||
const weatherQuery = useQuery({
|
const weatherQuery = useQuery({
|
||||||
queryKey: ['weather', { cityName }],
|
queryKey: ['weather', { cityName }],
|
||||||
queryFn: () => fetchWeather(city?.results[0]),
|
queryFn: () => fetchWeather(city?.results[0]),
|
||||||
enabled: !!city,
|
enabled: !!city,
|
||||||
refetchInterval: 1000 * 60 * 5, // requests the weather every 5 minutes
|
cacheTime: 1000 * 60 * 60 * 6, // the weather is cached for 6 hours
|
||||||
|
staleTime: 1000 * 60 * 5, // the weather is considered stale after 5 minutes
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -41,13 +47,13 @@ const fetchCity = async (cityName: string) => {
|
|||||||
* @param coordinates of the location the weather should be fetched
|
* @param coordinates of the location the weather should be fetched
|
||||||
* @returns weather of specified coordinates
|
* @returns weather of specified coordinates
|
||||||
*/
|
*/
|
||||||
const fetchWeather = async (coordinates?: Coordinates) => {
|
async function fetchWeather(coordinates?: Coordinates) {
|
||||||
if (!coordinates) return;
|
if (!coordinates) return null;
|
||||||
const { longitude, latitude } = coordinates;
|
const { longitude, latitude } = coordinates;
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min¤t_weather=true&timezone=Europe%2FLondon`
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min¤t_weather=true&timezone=Europe%2FLondon`
|
||||||
);
|
);
|
||||||
return (await res.json()) as WeatherResponse;
|
return (await res.json()) as WeatherResponse;
|
||||||
};
|
}
|
||||||
|
|
||||||
type Coordinates = { latitude: number; longitude: number };
|
type Coordinates = { latitude: number; longitude: number };
|
||||||
|
|||||||
Reference in New Issue
Block a user