簡體   English   中英

React鈎子形式強鍵入Controller的render方法的value參數

[英]Strongly typing the value parameter of the render method of the Controller in React hook form

使用 react 鈎子形式, Controller#render方法被傳遞了一個包含當前控制值的value參數。 它的類型為any ,是否可以強類型,例如,如果由 controller 管理的組件要呈現string ,則render方法的 value 參數應在 value 參數中鍵入為string 這是一個沙盒

import { useForm, Controller } from "react-hook-form";

type Person = {
  firstName: string;
  lastName: string;
};

export default function App() {
  const { handleSubmit, control, register } = useForm<Person>({
    defaultValues: {
      firstName: "John",
      lastName: "Smith"
    }
  });

  const onSubmit = (data: Person) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstName" ref={register} />
      <Controller
        control={control}
        name="lastName"
        // *************************************
        // ====> value is typed as `any`, how to type it as the bound enity, i.e. string from Person.lastName?
        // *************************************
        render={({ onChange, name, value }) => (
          <input
            name={name}
            value={value}
            onChange={onChange}
          />
        )}
      />

      <input type="submit" value="Submit"></input>
    </form>
  );
}

解決方案 v7

從 v7 開始,與 v6 相比,RHF 對 TypeScript 的支持要好得多。 因此,例如,關於register方法的重大變化。 如果可能,請更新到此版本。

編輯 React Hook 表單 - TS 值

解決方案 v6

如果您需要使用 v6,RHF 提供的這個小package將使Controller組件更加類型安全。

編輯 React Hook 表單 - TS Value v6

運行 RHF 7.18.0 和 Typescript 4.4.4。 Controller定義似乎已經改變。 找不到輸入 Contoller 的valuedefaultValue的方法。 我正在嘗試創建一個通用的Select字段,如下所示,但是當將通用 T 作為第二種類型的 Contoller 傳遞時,ESLint 會抱怨。

import Box from "@mui/material/Box";
import Checkbox from "@mui/material/Checkbox";
import InputLabel from "@mui/material/InputLabel";
import ListItemText from "@mui/material/ListItemText";
import MenuItem from "@mui/material/MenuItem";
import Select, { SelectProps } from "@mui/material/Select";
import { Control, Controller, FieldValues } from "react-hook-form";

type UnBox<T> = T extends (infer U)[] ? U : T;

export interface IOptions<T> {
  value: T;
  displayedLabel: string;
}

type ISelectFieldProps<T extends Array<string | number> | string | number> =
  SelectProps<T> & {
    name: string;
    control: Control;
    options: Array<IOptions<T extends Array<string | number> ? UnBox<T> : T>>;
    optionsAsCheckBox?: boolean;
  };

const SelectField = <T extends Array<string | number> | string | number>({
  name,
  control,
  defaultValue,
  label,
  options,
  optionsAsCheckBox = false,
  ...rest
}: ISelectFieldProps<T>): JSX.Element => {
  return (
    <Controller<FieldValues, T>  <--error here. Changing T to any fixed, but then value and defaultValue are any and not typeof T...
      name={name}
      control={control}
      defaultValue={defaultValue}
      render={({ field: { onChange, onBlur, value } }) => (
        <Box>
          <InputLabel id={name}>{label}</InputLabel>
          <Select
            label={label}
            onChange={onChange}
            value={value}
            onBlur={onBlur}
            {...rest}
          >
            {options.map((option) => (
              <MenuItem key={option.value} value={option.value}>
                {optionsAsCheckBox && (
                  <Checkbox checked={value.indexOf(option.value) > -1} />
                )}
                <ListItemText primary={option.displayedLabel} />{" "}
              </MenuItem>
            ))}
          </Select>
        </Box>
      )}
    />
  );
};

export default SelectField;

調用它的例子

<SelectField<Array<string>>
        name="ton"
        multiple
        control={control}
        input={<OutlinedInput label="Tag" />}
        renderValue={(selected) => selected.join(", ")}
        defaultValue={[]}
        label="Ton"
        options={[
          {
            value: "A",
            displayedLabel: "AAAA",
          },
          {
            value: "B",
            displayedLabel: "BBBB",
          },
          {
            value: "C",
            displayedLabel: "CCCCC",
          },
        ]}
      />

錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM