带有 MUI 自动完成、FreeSolo 和依赖字段的 React Hook Form

KaM*_*aTa 3 reactjs material-ui react-hook-form

我正在尝试从此 JSON 文件ZipCode / City / State创建(意大利语CAP / Citt\xc3\xa0 / Provincia)依赖字段(这里也是存储库)。我正在使用 React Hook Form v7 和 MUI v5.4.4。我想使用 MUI Autocomplete 组件和props 来实现这 3 个字段,以便让用户插入自定义输入值(如果 JSON 列表中不存在)。FreeSolo

\n

我试图让它发挥作用,但没有成功。我怎样才能实现它?此外,自动完成组件的验证不起作用。

\n

这是我写的codesandbox

\n

kno*_*fel 5

您的代码中有几个问题:

\n
    \n
  • 你忘记将rules道具传递给你的<Controller />
  • \n
  • 当前选定的值将作为第二个参数传递给<Autocomplete />\ 的onChange处理程序
  • \n
  • 您需要使用 RHF 的watch方法对这 3 个相关字段的更改做出反应,并相应地过滤其他选择的选项
  • \n
  • 您需要使用flatMap而不是map用于邮政编码选项的映射,就像option.cap数组一样
  • \n
\n
export default function PersonalDetails() {\n  const { watch } = useFormContext();\n\n  const { postalCode, city, state } = watch("personalDetails");\n\n  return (\n    <Card variant="outlined" sx={{ width: 1 }}>\n      <CardContent>\n        <Grid container item spacing={2}>\n           <Grid item xs={12} lg={3}>\n            <SelectFree\n              name="personalDetails.postalCode"\n              label="ZIP (CAP)"\n              options={options\n                .filter((option) =>\n                  city || state\n                    ? option.nome === city || option.sigla === state\n                    : option\n                )\n                .flatMap((option) => option.cap)}\n              rules={{ required: "Richiesto" }}\n            />\n          </Grid>\n          <Grid item xs={12} lg={10}>\n            <SelectFree\n              name="personalDetails.city"\n              label="City (Citt\xc3\xa0)"\n              options={options\n                .filter((option) =>\n                  postalCode || state\n                    ? option.cap.includes(postalCode) || option.sigla === state\n                    : option\n                )\n                .map((option) => option.nome)}\n              rules={{ required: "Richiesto" }}\n            />\n          </Grid>\n          <Grid item xs={12} lg={2}>\n            <SelectFree\n              name="personalDetails.state"\n              label="State (Sigla)"\n              options={options\n                .filter((option) =>\n                  city || postalCode\n                    ? option.nome === city || option.cap.includes(postalCode)\n                    : option\n                )\n                .map((option) => option.sigla)}\n              rules={{ required: "Richiesto" }}\n            />\n          </Grid>\n        </Grid>\n      </CardContent>\n    </Card>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n
export default function SelectFree({\n  name,\n  rules,\n  options,\n  getOptionLabel,\n  ...rest\n}) {\n  const { control } = useFormContext();\n\n  return (\n    <Controller\n      name={name}\n      control={control}\n      rules={rules}\n      defaultValue={null}\n      render={({\n        field: { ref, ...field },\n        fieldState: { error, invalid }\n      }) => {\n        return (\n          <Autocomplete\n            {...field}\n            freeSolo\n            handleHomeEndKeys\n            options={options}\n            getOptionLabel={getOptionLabel}\n            renderInput={(params) => (\n              <TextField\n                {...params}\n                {...rest}\n                inputRef={ref}\n                error={invalid}\n                helperText={error?.message}\n              />\n            )}\n            onChange={(e, value) => field.onChange(value)}\n            onInputChange={(_, data) => {\n              if (data) field.onChange(data);\n            }}\n          />\n        );\n      }}\n    />\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

编辑无价的汉密尔顿-pdxlww

\n

更新

\n

由于您有一个非常大的 json 文件,您有两个选项可以优化性能:

\n
    \n
  • filterOptions通过 ->的属性限制选项数量<Autocomplete />-> 该createFilterOptions函数可以配置为设置限制
  • \n
  • 在将选项传递给之前添加一个useMemo钩子来过滤和映射选项<Autocomplete />,例如,现在在其他字段(firstName,,, )的每次lastName输入更改时address,选项将被重新计算
  • \n
\n

编辑 trusting-franklin-9rqbls

\n