Я использую React Router Dom v6. Я хотел бы сохранить некоторые параметры поиска объекта в URL-адресе. Сейчас я в основном делаю что-то вроде этого:
const [searchParams, setSearchParams] = useSearchParams();
const allSearchParams = useMemo(() => {
const params: Record<string, string> = {};
for (const [key, value] of searchParams.entries()) {
if (value.startsWith('{') || value.startsWith('[')) {
try {
params[key] = JSON.parse(value);
} catch {
params[key] = value;
}
} else {
params[key] = value;
}
}
return params;
}, [searchParams]);
И когда я пишу URL-адрес, я делаю:
const newF: Record<string, string> = { ...nextFilter };
Object.keys(newF).forEach((key) => {
if (typeof newF[key] === 'object' && newF[key]) {
newF[key] = JSON.stringify(newF[key]);
}
});
setSearchParams(createSearchParams(newF), {
replace: replaceSearch,
});
Но это кажется довольно хакерским. Есть ли правильный способ правильно и безопасно хранить объекты в URL-адресе? Например:
const filters = {
name: "user1",
region: {
city: "Sydney",
country: "Australia"
}
}
Как указывает Undo, единого правильного способа сделать это не существует. Вам решать, как вы хотите кодировать/декодировать свои данные в URL-адресе. Это субъективно, поэтому я голосую за то, чтобы закрыть как «уверенное мнение».
Вы можете упростить процесс кодирования и декодирования. Вы можете использовать следующие функции; вы можете добавить их в свой собственный файл и импортировать их:
import {createSearchParams} from "react-router-dom"
export const encodeSearchParams = (params) => createSearchParams(params);
export const decodeSearchParams = (searchParams) => {
return [...searchParams.entries()].reduce((acc, [key, val]) => {
try {
return {
...acc,
[key]: JSON.parse(val)
};
} catch {
return {
...acc,
[key]: val
};
}
}, {});
};
Таким образом, вам не нужно запоминать их. И вы можете использовать их, как показано ниже, например:
function HomePage() {
const [searchParams, setSearchParams] = useSearchParams();
function handleQueryParamsChange() {
const filters = {
name: "user1",
region: {
city: "Sydney",
country: "Australia"
}
};
const params = {
filters: JSON.stringify(filters),
anotherField: "Simple String"
};
setSearchParams(encodeSearchParams(params));
}
console.info(decodeSearchParams(searchParams).filters);
console.info(decodeSearchParams(searchParams).anotherField);
return (
<div>
<button onClick = {handleQueryParamsChange} className = "page">
Update query params
</button>
</div>
);
}
Нет правильного способа сделать это, некоторые делают это так же, как и вы, и сохраняют строку json, закодированную в URL-адресе. Другие кодируют его с помощью base64 или аналогичного (и удаляют знак равенства). Другой более сложный, но более чистый подход — сохранить объект в базе данных и получить его с идентификатором (лучше всего, если объект огромен).