Brackets in JavaScript/React in Query Params

84 Views Asked by At

How do I achieve the brackets as shown in this URL?

{{url}}/invoices?orderBy[created_at]=asc&orderBy[reference_number]=asc

screenshot from Postman showing URL format

invoiceApi.js

import api from '@/api/api';
import { useMutation, useQuery } from '@tanstack/react-query';

const invoiceUrl = `/invoices`;

export const fetchInvoices = (
  {
    pageNumber,
    pageSize,
    search = '',
    orderBy = { created_at: 'asc', reference_number: 'asc' },
  },
  config
) => {
  const params = {
    page: pageNumber + 1,
    size: pageSize,
    search,
    orderBy, //  no spread syntax here
  };
  return api.get(invoiceUrl, {
    ...config,
    params: {
      ...config.params,
      ...params,
    },
  });
};

export const useFetchInvoicesQuery = (data) => {
  const { pageNumber, pageSize, search } = data;
  return useQuery({
    queryKey: ['invoices', pageNumber, pageSize, search],
    queryFn: () => fetchInvoices(data),
  });
};

InvoiceAutocomplete.js

import { useFetchInvoicesQuery } from '@/api/invoiceApi';
import { useDebounceValue } from '@/hooks/useDebounceValue';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import PropTypes from 'prop-types';
import React, { useState } from 'react';

export default function renderInvoiceAutocomplete(params) {
  return <InvoiceAutocomplete {...params} />;
}

const InvoiceAutocomplete = ({
  field,
  form: { touched, errors, setFieldValue },
  ...props
}) => {
  const [inputValue, setInputValue] = useState('');
  const debouncedInputValue = useDebounceValue(inputValue, 500);

  const { data: response, isLoading } = useFetchInvoicesQuery({
    pageNumber: 0,
    pageSize: 50,
    search: debouncedInputValue,
  });

  const handleChange = (_, newValue, reason) => {
    if (reason === 'clear') {
      setFieldValue(field.name, { id: '', invoice_number: '' });
      setFieldValue('total_amount', undefined);
      return;
    }
    setFieldValue(field.name, newValue);
    setFieldValue('total_amount', newValue?.amount);
  };

  const handleInputChange = (_, newInputValue) => {
    setInputValue(newInputValue);
  };

  return (
    <Autocomplete
      {...field}
      getOptionLabel={(option) =>
        typeof option === 'string' ? option : option?.invoice_number || ''
      }
      renderOption={(props, option) => {
        return (
          <li {...props} key={option.id}>
            {option?.invoice_number}
          </li>
        );
      }}
      filterOptions={(x) => x}
      options={response?.data?.data || []}
      autoComplete
      includeInputInList
      filterSelectedOptions
      noOptionsText={isLoading ? 'Loading...' : 'No data'}
      onChange={handleChange}
      inputValue={inputValue}
      onInputChange={handleInputChange}
      renderInput={(params) => (
        <TextField
          {...params}
          {...props}
          error={touched[field.name] && errors[field.name] ? true : false}
          helperText={
            touched[field.name] &&
            errors[field.name] &&
            String(errors[field.name].id)
          }
        />
      )}
      fullWidth
    />
  );
};

InvoiceAutocomplete.propTypes = {
  field: PropTypes.object.isRequired,
  form: PropTypes.object.isRequired,
};
1

There are 1 best solutions below

4
Phil On BEST ANSWER

Axios has features to handle this use case specifically.

Pass your query param data via the params option and it will automatically translate objects to use the square-bracket notation.

const invoiceUrl = 'https://echo.zuplo.io/'; // just for the demo
const api = axios.create();

const fetchInvoices = (
  {
    pageNumber,
    pageSize,
    search = '',
    orderBy = { created_at: 'asc', reference_number: 'asc' },
  },
  config = {},
) => {
  const params = {
    page: pageNumber + 1,
    size: pageSize,
    search,
    orderBy, //  no spread syntax here
  };
  return api.get(invoiceUrl, {
    ...config,
    params: {
      ...config.params,
      ...params,
    },
  });
};

fetchInvoices({
  pageNumber: 1,
  pageSize: 10,
}).then(({ data }) => {
  console.log(data.url);
});
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>