仅选择一个选项时发送具有多选的数组

Send an array with multiselect when selected only one option

我使用 react-select 库来处理表单。

字段定义:

<AsyncSelect 
    isMulti={true} 
    defaultOptions 
    cacheOptions 
    onChange={handleSelectChange} 
    name={formData.name}
    defaultValue={formData.defaultValue} 
    loadOptions={props.loadOptions}
/>

库使用输入字段来存储选定的值。 例如:

<input name="artists_ids" type="hidden" value="3f9da869-a230-4fc6-8012-40a5f06d694e">
<input name="artists_ids" type="hidden" value="d9741ab8-784e-45bf-af92-0416e97730da">

为了处理表单数据,我使用 FormData 对象:

    const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
        event.preventDefault();
        Router.post(props.routing, {body: new FormData(event.currentTarget)})
        //...
    })

API 仅限于获取 ID 数组。

当用户选择多个值时一切正常:

{
    "artists_ids":["3f9da869-a230-4fc6-8012-40a5f06d694e","d9741ab8-784e-45bf-af92-0416e97730da"]
}

问题

当用户尝试仅发送一个选定值时,FormData 对象将数据转换为字符串而不是数组:

{
    "artists_ids": "3f9da869-a230-4fc6-8012-40a5f06d694e"
}

无效的解决方案:

问题

你知道如何在用户只选择一个字段的情况下发送数组吗?

我可能只是将 artist_ids 包装在一个数组中,因为它还不是一个数组。由于您在某种程度上受到 API 和通用 AddForm 函数的限制,因此解决方案可能涉及使该函数稍微更灵活一些。

考虑到这个目标,我会在您的 IFormComponentProps 界面中添加一个可选的 transform 功能。未定义时,将新的 transform 属性默认为恒等函数 ((x) => x)。这确保 handleSubmit 将保持与现有形式的向后兼容。

AddForm 中,将 props.transform 应用于 Router.postRequestInit 参数,如下所示:

export function AddForm(props: IFormComponentProps) {
    const { transform = (x) => x } = props
// ...
    const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
        event.preventDefault();
        Router.post(props.routing, transform({body: new FormData(event.currentTarget)}))
// ...
}

因为 BodyInit 可以是一个字符串,你应该能够提供一个自定义函数,将你的 new FormData 转换成一个对象(artists_ids 强制成为一个数组),然后 JSON.stringify 那个对象,这样你最终调用 Router.post 与:

{
  body: JSON.stringify(transformedFormDataObject),
  headers: { 'Content-Type': 'application/json' }
}

这应该可以解决问题(如果 API 可以处理内容类型)并且应该给您更大的灵活性,如果您将来需要的话。

如果 API 无法处理内容类型,您需要在处理后将普通对象转换回新的 FormData 对象以确保 artists_ids是一个数组(而不是 JSON.stringifying 它)。