带有 MUI Autocomplete、FreeSolo 和依赖字段的 React Hook 表单

React Hook Form with MUI Autocomplete, FreeSolo and dependent fields

提问人:KaMZaTa 提问时间:3/15/2022 更新时间:3/17/2022 访问量:6753

问:

我正在尝试从这个JSON文件创建(意大利语)依赖字段(这里也是存储库)。我正在使用 React Hook Form v7 和 MUI v5.4.4。我想使用带有 props 的 MUI 自动完成组件实现这 3 个字段,以便让用户插入自定义输入值(如果 JSON 列表中不存在)。ZipCode / City / StateCAP / Città / ProvinciaFreeSolo

我试图让它起作用,但它没有。我该如何实现?此外,自动完成组件的验证不起作用。

这是我写的代码沙盒

reactjs material-ui react-hook-form

评论

0赞 knoefel 3/16/2022
你说的依赖是什么意思?如果用户选择邮政编码,那么城市选择应该只过滤具有该邮政编码的城市吗?
0赞 KaMZaTa 3/16/2022
@knoefel是的,没错。反之亦然。

答:

5赞 knoefel 3/16/2022 #1

您的代码中存在几个问题:

  • 你忘了把道具传给你rules<Controller />
  • 当前选定的值将作为第二个参数传递给 的处理程序<Autocomplete />onChange
  • 您需要使用 RHF 的方法对这 3 个相关字段的变化做出反应,并相应地过滤其他选择的选项watch
  • 您需要使用而不是用于邮政编码选项的映射,就像数组一样flatMapmapoption.cap
export default function PersonalDetails() {
  const { watch } = useFormContext();

  const { postalCode, city, state } = watch("personalDetails");

  return (
    <Card variant="outlined" sx={{ width: 1 }}>
      <CardContent>
        <Grid container item spacing={2}>
           <Grid item xs={12} lg={3}>
            <SelectFree
              name="personalDetails.postalCode"
              label="ZIP (CAP)"
              options={options
                .filter((option) =>
                  city || state
                    ? option.nome === city || option.sigla === state
                    : option
                )
                .flatMap((option) => option.cap)}
              rules={{ required: "Richiesto" }}
            />
          </Grid>
          <Grid item xs={12} lg={10}>
            <SelectFree
              name="personalDetails.city"
              label="City (Città)"
              options={options
                .filter((option) =>
                  postalCode || state
                    ? option.cap.includes(postalCode) || option.sigla === state
                    : option
                )
                .map((option) => option.nome)}
              rules={{ required: "Richiesto" }}
            />
          </Grid>
          <Grid item xs={12} lg={2}>
            <SelectFree
              name="personalDetails.state"
              label="State (Sigla)"
              options={options
                .filter((option) =>
                  city || postalCode
                    ? option.nome === city || option.cap.includes(postalCode)
                    : option
                )
                .map((option) => option.sigla)}
              rules={{ required: "Richiesto" }}
            />
          </Grid>
        </Grid>
      </CardContent>
    </Card>
  );
}
export default function SelectFree({
  name,
  rules,
  options,
  getOptionLabel,
  ...rest
}) {
  const { control } = useFormContext();

  return (
    <Controller
      name={name}
      control={control}
      rules={rules}
      defaultValue={null}
      render={({
        field: { ref, ...field },
        fieldState: { error, invalid }
      }) => {
        return (
          <Autocomplete
            {...field}
            freeSolo
            handleHomeEndKeys
            options={options}
            getOptionLabel={getOptionLabel}
            renderInput={(params) => (
              <TextField
                {...params}
                {...rest}
                inputRef={ref}
                error={invalid}
                helperText={error?.message}
              />
            )}
            onChange={(e, value) => field.onChange(value)}
            onInputChange={(_, data) => {
              if (data) field.onChange(data);
            }}
          />
        );
      }}
    />
  );
}

编辑 priceless-hamilton-pdxlww

更新

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

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

编辑 trusting-franklin-9rqbls

评论

0赞 KaMZaTa 3/16/2022
谢谢,它似乎部分有效。使用“实际”,我收到 ZIP 和 STATE 字段的此错误:30020 如何插入唯一键?comuni.jsonWarning: Encountered two children with the same key, . Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
0赞 KaMZaTa 3/17/2022
应该是唯一的键。codiceCatastale
0赞 KaMZaTa 3/17/2022
此外,列表中有很多重复的结果。也许我应该实现某种自定义过滤器?mui.com/components/autocomplete/#custom-filter
0赞 KaMZaTa 3/17/2022
我认为它应该像这样工作,但似乎有点慢。也许我只能显示前 10 个结果。你知道我该如何优化它吗?你觉得怎么样?codesandbox.io/s/empty-architecture-2mqdms
1赞 KaMZaTa 3/17/2022
它现在似乎像一个魅力!谢谢你的努力。