I have a react app and I'm trying to use a table component.
This table component has multiple ways of filtering the table, and I want to be able to update the URL with these filters so that when I navigate away and go back, the table can read from the url params and have the table react accordingly.
I am able to get my table to already do something like this, but when working with multiple params, I'm a bit lost. My issue is that using history.replace
or history.push` will overwrite the previous params, and then updating them will only just append more params when I want to simply replace them
Here's what I have working already:
const useQueryParams = () => {
const params = new URLSearchParams(useLocation().search);
const startingAfter = params.get('startingAfter');
const endingBefore = params.get('endingBefore');
const status = params.get('status');
return { params, startingAfter, endingBefore, status };
}
export const MyComponent = () => {
const history = useHistory();
const location = useLocation();
const { params, startingAfter, endingBefore, status } = useQueryParams();
const [statusFilter, setStatusFilter] = useState<IStatus | string>(
Status.Pending
);
const [dateFilter, setDateFilter] = useState<{
appointmentStartingAfter?: string;
appointmentEndingBefore?: string;
}>({
appointmentStartingAfter: undefined,
appointmentEndingBefore: undefined,
});
useEffect(() => {
if (startingAfter || endingBefore) {
setDateFilter({
appointmentStartingAfter: moment(startingAfter).toISOString() || undefined,
appointmentEndingBefore: moment(endingBefore).toISOString() || undefined,
});
}
if (status) {
setStatusFilter(status);
}
}, [startingAfter, endingBefore, status]);
// ......
const handleDateChange = (momentDateRange) => {
const startingAfter = momentDateRange[0].subtract(1, 'day');
const endingBefore = momentDateRange[1].add(1, 'day');
history.replace({
search: `startingAfter=${startingAfter.format('YYYY-MM-DD')}&endingBefore=${endingBefore.format('YYYY-MM-DD')}`,
});
setDateFilter({
appointmentStartingAfter: startingAfter.toISOString() || undefined,
appointmentEndingBefore: endingBefore.toISOString() || undefined,
});
};
const handleStatusFilter = (value: string) => {
history.replace({
search: `status=${value || 'ALL_DOCUMENTS'}`,
});
setStatusFilter(value);
};
return (
<>
// ......
<DatePicker.RangePicker defaultValue={initialDates} style={{ marginRight: 20 }} onChange={handleDateChange} />
<CareDocumentStatusFilter value={statusFilter} onChange={handleStatusFilter} />
</>
);
}
I'm able to get the URLs working with history.replace
or history.push
but it will overwrite each other when I want them to remain persistent.
For example,
history.replace({
search: `startingAfter=${startingAfter.format('YYYY-MM-DD')}&endingBefore=${endingBefore.format('YYYY-MM-DD')}`,
});
// localhost:3000/xyz?startingAfter=2021-08-06&endingBefore=2021-08-19
But then in handleStatusFilter
history.replace({
search: `status=${value || 'ALL_DOCUMENTS'}`,
});
// localhost:3000/xyz?status=CREATED
In the example above, status
will overwrite the params when the intended URL should look something like:
localhost:3000/xyz?startingAfter=2021-08-06&endingBefore=2021-08-19&status=CREATED
in my different attempts, when I want to update this, instead of changing the params, the params just seem to append more and end up looking like this:
localhost:3000/xyz?startingAfter=2021-08-06&endingBefore=2021-08-19&status=CREATED?startingAfter=xxxx&endingBefore=yyyy&status=zzzz
I do have react-router-dom
available to be used as well.