Bonjour à tous,

Je dois extraire les données d'une base de donnée pour afficher des graphiques.

Je dois aussi ajouter deux boutons pour ouvrir un calendreir afin de sélectionner une date de début et une date de fin pour avoir des graphiques entre ces deux dates. Pour cela, j'essaye react-native-modal-datetime-picker ainsi que dayjs pour formater mes dates

Il faut savoir qu'une station peut être arretée et que la dernière mesure prise peut etre ancinne de 1 ou 2 mois. La date par dfaut des deux calendriers, doit correspondre à la date de la dernière mesure prise.

Le premier problème que j'ai, c'est que lorsque je charge ma page (tabs)/station/[id].tsx, les dates dateFrom et dateTo sont incunnue. Je défini une date très ancinne

Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
const [dateFrom, setDateFrom] = useState('1900-01-01'); // TODO new Date(dayjs("2025-05-01").format("YYYY-MM-DD")
const [dateTo, setDateTo] = useState('1900-01-01');

Puis je fais une requete sur ma base de donnée pour avoir des informations sur ma station et les mesures enregistrées. Je connais ainsi la date de la dernière mesure

Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 const params = useLocalSearchParams() as {id: string};
 const {data, isFetching} = useFetchQuery("/getstation/[id]/[from]/[to]", {id: params.id, from: dateFrom, to: dateTo})
 const measures = data?.stations?.[0].measures
 const station = data?.stations?.[0]
 console.log(station?.latest_measure)

Je dois donc maintenant mettre à jour mon état

Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
 if(station?.latest_measure != undefined){
 	setDateTo(dayjs(station?.latest_measure).format("YYYY-MM-DD"))
 }

Le problème est que expo affiche cette erreur

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

Je pesne que
  • setDateFrom
  • useFetchQuery
  • et re- setDateFrom


Génère un re-render

Comment feriez-vous pour éviter cet erreur?

A ce niveau
Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
if(station?.latest_measure != undefined){
 	setDateTo(dayjs(station?.latest_measure).format("YYYY-MM-DD"))
 }
Peut-on de ne pas faire un render?
Par exemple, est-ce que le premier render puisse etre effectué après ceci
Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 const params = useLocalSearchParams() as {id: string};
 const {data, isFetching} = useFetchQuery("/getstation/[id]/[from]/[to]", {id: params.id, from: dateFrom, to: dateTo})
 const measures = data?.stations?.[0].measures
 const station = data?.stations?.[0]
 console.log(station?.latest_measure)

Ou est-ce possible de faire un render juste avant le return qui contient le DOM

useQuery
Aussi, je pose vraiment la question, si ma manière de faire un useQuery est bien formulée. (J'ai suivi un tuto)

Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 const params = useLocalSearchParams() as {id: string};
 const {data, isFetching} = useFetchQuery("/getstation/[id]/[from]/[to]", {id: params.id, from: dateFrom, to: dateTo})
fait appel à cette fonction que j'ai un peu noettoyer pour vous facilité la lecture

Je me demande comment je pourrai optimiser ceci surtout parce que dès que les dates 'dateFrom' et 'dateTo' devront refaire un useFetchQuery pour recharger les mesures entre les dates sélectionnées

Code typescript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 
import { QueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query'
 
const endpoint = "https://api.eco-sensors.ch/dashboard"
 
type API = {
    '/getstation/[id]/[from]/[to]': {
        response: number, 
        id: number,
        method: string,
        next: string | null,
        fields: {
            id_field: number,
            field_name: string,
            field_longname: string,
            field_city: string,
            field_lat: number,
            field_lng: number
        }[],
        stations: {
            id_field: number,
            field_name: string,
            id_station: number,
            station_longname: string,
            id_station_type: number,
            station_type_name: string,
            station_archive: number,
            lat: number,
            lng: number,
            alt: number,
            measures?: {
                datasets?: {
                    data?:{
                        value: number,
                        label: string,
                        date: string,
                        dataPointText: number
                    }[],
                    label: string,
                    showLine:boolean,
                    borderColor:string,
                    backgroundColor:string,
                    pointStyle:string,
                    fill:boolean,
                    borderWidth:number,
                    pointRadius:number,
                    type:string,
                },
                labels: {}[],
                unit: string,
                chartContainer: string,
                id_sensor_type: number,
                id_sensor:number,
                sensor_type: string,
                sensor_type_longname: string,
                sensor_type_awe: string,
            }[],
            measures_found: number,
            station_found: number,
            latest_measure: string,
        }[],
        map_center:{
            lat: number,
            lng: number,
        },
    }
 
 
 
}
 
export function useFetchQuery<T extends keyof API>(path: T, params?: Record<string, string | number>){
    const localurl = endpoint + Object.entries(params ?? {}).reduce((acc, [key, value]) => acc.replaceAll(`[${key}]`, value.toString()) as T, path)
 
    return useQuery({
        queryKey: [localurl],
        //refetchIntervalInBackground: true,  
        //refetchInterval: 60000, // 60 000 ms = 60 secondes
        //refetchOnWindowFocus: false,
        //staleTime:60000,
        queryFn: async () => { // Comment on reécupère les résultat
            //await wait(2);
            return fetch(localurl,{
                headers:{
                    Accept: 'application/json',
                }
            }).then((r) => r.json() as Promise<API[T]>); // Convertir le résultat (r) en json
        },
    })
}
 
function wait (duration: number){
    return new Promise((resolve) => setTimeout(resolve, duration * 1000))
}

merci pour votre précieuse aide