2

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.

nyphur
  • 2,404
  • 2
  • 24
  • 48

1 Answers1

0

So I interestingly stumbled upon this answer and it seemed to solve my issue. I believe using URLSearchParams.set was the key here. I don't entirely super understand the inner workings... but it works! Here is my solution:

  const handleDateChange = (momentDateRange) => {
    const startingAfter = momentDateRange[0].subtract(1, 'day');
    const endingBefore = momentDateRange[1].add(1, 'day');

    // This was important!
    params.set('startingAfter', startingAfter.format('YYYY-MM-DD'));
    params.set('endingBefore', endingBefore.format('YYYY-MM-DD'));

    history.push({
      // and so was this ...?
      pathname: location.pathname,
      search: params.toString(),
    });

    setDateFilter({
      appointmentStartingAfter: startingAfter.toISOString() || undefined,
      appointmentEndingBefore: endingBefore.toISOString() || undefined,
    });
  };

  const handleStatusFilter = (value: string) => {
    // This was important!
    params.set('status', value || 'ALL_DOCUMENTS');

    history.push({
      // ... and so was this?
      pathname: location.pathname,
      search: params.toString(),
    })

    setStatusFilter(value);
  };
nyphur
  • 2,404
  • 2
  • 24
  • 48