-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathuseScenarioQueryParams.ts
87 lines (74 loc) · 3.06 KB
/
useScenarioQueryParams.ts
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
import { useEffect, useCallback, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { updateSelectedTrainId, updateTrainIdUsedForProjection } from 'reducers/simulationResults';
import {
getSelectedTrainId,
getTrainIdUsedForProjection,
} from 'reducers/simulationResults/selectors';
import { useAppDispatch } from 'store';
type SimulationParams = {
projectId: string;
studyId: string;
scenarioId: string;
};
const useScenarioQueryParams = () => {
const location = useLocation();
const navigate = useNavigate();
const dispatch = useAppDispatch();
const {
projectId: urlProjectId,
studyId: urlStudyId,
scenarioId: urlScenarioId,
} = useParams() as SimulationParams;
const localKey = `useScenarioQueryParams_project${urlProjectId}_study${urlStudyId}_scenario${urlScenarioId}`;
const searchParams = useMemo(() => new URLSearchParams(location.search), [location.search]);
const reduxSelectedTrainId = useSelector(getSelectedTrainId);
const reduxProjectionTrainId = useSelector(getTrainIdUsedForProjection);
// Helper function to get a parameter from the URL, or if absent from local storage
const getParamFromUrlOrStorage = useCallback(
(paramName: string) =>
searchParams.get(paramName) || localStorage.getItem(`${localKey}_${paramName}`) || undefined,
[localKey, searchParams]
);
// Helper function to get a parameter from the URL or local storage
const setParamsInUrlAndStorage = useCallback(
(paramName: string, paramValue: string | undefined) => {
if (paramValue === undefined) {
searchParams.delete(paramName);
localStorage.removeItem(`${localKey}_${paramName}`);
} else {
searchParams.set(paramName, paramValue);
localStorage.setItem(`${localKey}_${paramName}`, paramValue);
}
navigate(`${location.pathname}?${searchParams.toString()}`, { replace: true });
},
[localKey, searchParams, location.pathname, navigate]
);
// Update the redux store on page load
useEffect(() => {
const selectedTrainFromUrl = getParamFromUrlOrStorage('selected_train');
const projectionFromUrl = getParamFromUrlOrStorage('projection');
if (selectedTrainFromUrl) {
dispatch(updateSelectedTrainId(Number(selectedTrainFromUrl)));
}
if (projectionFromUrl) {
dispatch(updateTrainIdUsedForProjection(Number(projectionFromUrl)));
}
}, [dispatch, getParamFromUrlOrStorage]);
// Update the URL and local storage on redux store change
useEffect(() => {
if (reduxSelectedTrainId?.toString() !== getParamFromUrlOrStorage('selected_train')) {
setParamsInUrlAndStorage('selected_train', reduxSelectedTrainId?.toString());
}
if (reduxProjectionTrainId?.toString() !== getParamFromUrlOrStorage('projection')) {
setParamsInUrlAndStorage('projection', reduxProjectionTrainId?.toString());
}
}, [
reduxSelectedTrainId,
reduxProjectionTrainId,
setParamsInUrlAndStorage,
getParamFromUrlOrStorage,
]);
};
export default useScenarioQueryParams;