- Convert all .js files to .tsx/.ts - Add types for data structures (MuseumRecord, Metrics, etc.) - Add type declarations for react-chartjs-2 - Configure tsconfig with relaxed strictness for gradual adoption - All components now use TypeScript
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
import { useEffect, useCallback } from 'react';
|
|
import { useSearchParams } from 'react-router-dom';
|
|
|
|
/**
|
|
* Sync state with URL search params
|
|
* @param {Object} state - Current state object
|
|
* @param {Function} setState - State setter function
|
|
* @param {Object} defaultState - Default state values
|
|
* @param {Array<string>} keys - Keys to sync with URL
|
|
*/
|
|
export function useUrlState(state, setState, defaultState, keys) {
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
|
|
// Initialize state from URL on mount
|
|
useEffect(() => {
|
|
const urlState = {};
|
|
let hasUrlParams = false;
|
|
|
|
keys.forEach(key => {
|
|
const value = searchParams.get(key);
|
|
if (value !== null) {
|
|
urlState[key] = value;
|
|
hasUrlParams = true;
|
|
}
|
|
});
|
|
|
|
if (hasUrlParams) {
|
|
setState(prev => ({ ...prev, ...urlState }));
|
|
}
|
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
// Update URL when state changes
|
|
const updateUrl = useCallback((newState) => {
|
|
const params = new URLSearchParams();
|
|
|
|
keys.forEach(key => {
|
|
const value = newState[key];
|
|
if (value && value !== defaultState[key]) {
|
|
params.set(key, value);
|
|
}
|
|
});
|
|
|
|
setSearchParams(params, { replace: true });
|
|
}, [keys, defaultState, setSearchParams]);
|
|
|
|
// Wrap setState to also update URL
|
|
const setStateWithUrl = useCallback((updater) => {
|
|
setState(prev => {
|
|
const newState = typeof updater === 'function' ? updater(prev) : updater;
|
|
updateUrl(newState);
|
|
return newState;
|
|
});
|
|
}, [setState, updateUrl]);
|
|
|
|
return setStateWithUrl;
|
|
}
|
|
|
|
export default useUrlState;
|