如何在JavaScript/React中生成带括号格式的URL查询参数?
问题:生成指定格式的orderBy请求参数URL
希望生成如下格式的URL:
{{url}}/invoices?orderBy[created_at]=asc&orderBy[reference_number]=asc
但当前在React项目的invoiceApi.js中直接传递orderBy对象作为请求参数时,无法得到该格式。以下是相关代码文件:
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, // 直接传递对象无法生成目标格式 }; 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, };
解决方案
问题出在HTTP客户端(如axios)默认会将嵌套对象序列化为数组格式,无法生成目标的扁平参数结构。需要手动将orderBy对象转换为orderBy[字段名]: 值的键值对格式:
修改invoiceApi.js中的fetchInvoices函数:
export const fetchInvoices = ( { pageNumber, pageSize, search = '', orderBy = { created_at: 'asc', reference_number: 'asc' }, }, config ) => { // 将orderBy对象转换为目标格式的参数 const orderByParams = Object.entries(orderBy).reduce((acc, [key, value]) => { acc[`orderBy[${key}]`] = value; return acc; }, {}); const params = { page: pageNumber + 1, size: pageSize, search, ...orderByParams, // 展开转换后的参数 }; return api.get(invoiceUrl, { ...config, params: { ...config.params, ...params, }, }); };
核心逻辑说明
- 用
Object.entries遍历orderBy对象的每个键值对 - 通过
reduce方法将每个键值对映射为orderBy[字段名]: 值的格式 - 把转换后的参数展开到
params中,替代原来直接传递的orderBy对象
修改后,请求URL会自动生成为你需要的orderBy[created_at]=asc&orderBy[reference_number]=asc格式。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

