You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Router路由的action函数中获取非受控多选Autocomplete的值?

解决React Router Form中Material UI多选Autocomplete值无法提交的问题

问题根源在于Material UI的Autocomplete(多选模式)并非原生表单控件,它不会自动将选中的值同步到表单的formData中——你看到的内部TextField只是负责展示输入状态,实际选中的标签数组并不会被作为表单字段提交。

下面提供两种可行的解决方式:

方式一:受控状态 + 隐藏Input

通过组件状态管理选中的标签,再用隐藏的原生input字段将值传递给formData:

import { useState } from 'react';
import { Form } from 'react-router-dom';
import { TextField, Autocomplete, Button } from '@mui/material';

export async function action({ request }) {
  const formData = await request.formData();
  const newPost = Object.fromEntries(formData);
  // 将逗号分隔的字符串还原为数组
  newPost.tags = newPost.tags ? newPost.tags.split(',') : [];
  // 后续处理逻辑
}

export default function NewPost() {
  const [selectedTags, setSelectedTags] = useState([]);

  return (
    <Form method="post">
      <TextField name="title" label="标题" fullWidth margin="normal" />
  
      <TextField name="body" label="正文" fullWidth margin="normal" multiline rows={4} />
  
      <Autocomplete
        multiple
        options={[1, 2, 3, 4, 5]}
        value={selectedTags}
        onChange={(event, newValue) => setSelectedTags(newValue)}
        renderInput={(params) => (
          <TextField {...params} label="标签" fullWidth margin="normal" />
        )}
      />
      {/* 隐藏input,用于提交选中的标签 */}
      <input
        type="hidden"
        name="tags"
        value={selectedTags.join(',')}
      />

      <Button type="submit" variant="contained" color="primary" style={{ marginTop: 16 }}>
        创建文章
      </Button>
    </Form>
  )
}

方式二:手动构建FormData提交

利用React Router的useSubmit钩子,在提交时手动将选中的标签加入formData:

import { useState, useCallback } from 'react';
import { Form, useSubmit } from 'react-router-dom';
import { TextField, Autocomplete, Button } from '@mui/material';

export async function action({ request }) {
  const formData = await request.formData();
  const newPost = {
    title: formData.get('title'),
    body: formData.get('body'),
    tags: JSON.parse(formData.get('tags')),
  };
  // 后续处理逻辑
}

export default function NewPost() {
  const [selectedTags, setSelectedTags] = useState([]);
  const submit = useSubmit();

  const handleSubmit = useCallback((event) => {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    // 将标签数组转为JSON字符串存入formData
    formData.set('tags', JSON.stringify(selectedTags));
    submit(formData, { method: 'post' });
  }, [selectedTags, submit]);

  return (
    <Form onSubmit={handleSubmit}>
      <TextField name="title" label="标题" fullWidth margin="normal" />
  
      <TextField name="body" label="正文" fullWidth margin="normal" multiline rows={4} />
  
      <Autocomplete
        multiple
        options={[1, 2, 3, 4, 5]}
        value={selectedTags}
        onChange={(event, newValue) => setSelectedTags(newValue)}
        renderInput={(params) => (
          <TextField {...params} label="标签" fullWidth margin="normal" />
        )}
      />

      <Button type="submit" variant="contained" color="primary" style={{ marginTop: 16 }}>
        创建文章
      </Button>
    </Form>
  )
}

两种方式的核心都是手动关联选中的标签值与表单提交数据,因为Autocomplete不会自动完成这个过程。

内容的提问来源于stack exchange,提问作者Ioannis Potouridis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:10:05