react-hook-form & react-select: 无法读取未定义的属性(读取 ‘name’)

huangapple go评论54阅读模式
英文:

react-hook-form & react-select : Cannot read properties of undefined (reading 'name')

问题

I cannot find a solution to make react-select and react-hook-form work.

I constantly get an error: Cannot read properties of undefined (reading 'name') and an error telling me that my field is required.

Here is my code in codesandbox: https://codesandbox.io/s/funny-elbakyan-h5xz8w?file=/src/App.tsx:0-1347

Below is my code:

// InputSelect.tsx
import React from "react";
import clsx from "clsx";
import { default as ReactSelect, MenuPlacement } from "react-select";

export type SelectOption = {
  value: string;
  label: string;
  key?: string;
};

export type InputSelectProps = {
  name: string;
  onChange: (value: any) => void;
  options: SelectOption[];
  error?: string;
};

const InputSelect: React.FC<InputSelectProps> = React.forwardRef(
  ({ id, options, name, onChange, label = "", error }, ref: React.Ref<any>) => {
    const prefix = React.useId();
    const inputId = id ?? `${prefix}-${name}`;
    const isError = Boolean(error);
    const [
      selectedOption,
      setSelectedOption
    ] = React.useState<SelectOption | null>(null);

    const handleChange = (event: any) => {
      console.log(event);
      setSelectedOption(event);

      // BUG is here - Cannot read properties of undefined (reading 'name')
      onChange(event);
    };

    return (
      <div className={clsx("c-form-field")}>
        <label
          className={clsx("c-form-field__label c-label pb-2.5")}
          htmlFor={inputId}
        >
          {label}
        </label>
        <ReactSelect
          name={name}
          options={options}
          onChange={(selectedOption) => {
            handleChange(selectedOption);
          }}
          value={selectedOption}
        />
        {/* Error messages */}
        {isError && <p className="text-danger">{error}</p>}
      </div>
    );
  }
);

export default InputSelect;

// App.tsx
import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";
import InputSelect from "./InputSelect";

enum OrganizationRole {
  ADMIN = "ADMIN",
  MANAGER = "MANAGER",
  USER = "USER"
}

interface FormData {
  email: string;
  role: string;
}

const options = Object.values(OrganizationRole).map((role) => ({
  value: role,
  label: role
}));

const App: React.FC = () => {
  const {
    handleSubmit,
    register,
    formState: { errors }
  } = useForm<FormData>({
    resolver: yupResolver(
      Yup.object({
        email: Yup.string().email("Invalid email address").required("Required"),
        role: Yup.string().required("Required")
      })
    )
  });

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <input type="email" {...register("email")} />
        {errors.email && <p>Email est requis</p>}
      </div>
      <div>
        <InputSelect
          label={"Role"}
          error={errors.role?.message}
          options={options}
          required
          {...register("role")}
        />
        {errors.role && <p>Rôle est requis</p>}
      </div>
      <button type="submit">Envoyer</button>
    </form>
  );
};

export default App;
英文:

I cannot find a solution to make react-select and react-hook-form work.

I constantly get an error: Cannot read properties of undefined (reading 'name') and an error telling me that my field is required.

Here is my code in codesandbox: https://codesandbox.io/s/funny-elbakyan-h5xz8w?file=/src/App.tsx:0-1347

Below is my code:

// InputSelect.tsx
import React from &quot;react&quot;;
import clsx from &quot;clsx&quot;;
import { default as ReactSelect, MenuPlacement } from &quot;react-select&quot;;
export type SelectOption = {
value: string;
label: string;
key?: string;
};
export type InputSelectProps = {
name: string;
onChange: (value: any) =&gt; void;
options: SelectOption[];
error?: string;
};
const InputSelect: React.FC&lt;InputSelectProps&gt; = React.forwardRef(
({ id, options, name, onChange, label = &quot;&quot;, error }, ref: React.Ref&lt;any&gt;) =&gt; {
const prefix = React.useId();
const inputId = id ?? `${prefix}-${name}`;
const isError = Boolean(error);
const [
selectedOption,
setSelectedOption
] = React.useState&lt;SelectOption | null&gt;(null);
const handleChange = (event: any) =&gt; {
console.log(event);
setSelectedOption(event);
// BUG is here - Cannot read properties of undefined (reading &#39;name&#39;)
onChange(event);
};
return (
&lt;div className={clsx(&quot;c-form-field&quot;)}&gt;
&lt;label
className={clsx(&quot;c-form-field__label c-label pb-2.5&quot;)}
htmlFor={inputId}
&gt;
{label}
&lt;/label&gt;
&lt;ReactSelect
name={name}
options={options}
onChange={(selectedOption) =&gt; {
handleChange(selectedOption);
}}
value={selectedOption}
/&gt;
{/* Error messages */}
{isError &amp;&amp; &lt;p className=&quot;text-danger&quot;&gt;{error}&lt;/p&gt;}
&lt;/div&gt;
);
}
);
export default InputSelect;
// App.tsx
import React from &quot;react&quot;;
import { useForm } from &quot;react-hook-form&quot;;
import { yupResolver } from &quot;@hookform/resolvers/yup&quot;;
import * as Yup from &quot;yup&quot;;
import InputSelect from &quot;./InputSelect&quot;;
enum OrganizationRole {
ADMIN = &quot;ADMIN&quot;,
MANAGER = &quot;MANAGER&quot;,
USER = &quot;USER&quot;
}
interface FormData {
email: string;
role: string;
}
const options = Object.values(OrganizationRole).map((role) =&gt; ({
value: role,
label: role
}));
const App: React.FC = () =&gt; {
const {
handleSubmit,
register,
formState: { errors }
} = useForm&lt;FormData&gt;({
resolver: yupResolver(
Yup.object({
email: Yup.string().email(&quot;Invalid email address&quot;).required(&quot;Required&quot;),
role: Yup.string().required(&quot;Required&quot;)
})
)
});
const onSubmit = (data: FormData) =&gt; {
console.log(data);
};
return (
&lt;form onSubmit={handleSubmit(onSubmit)}&gt;
&lt;div&gt;
&lt;input type=&quot;email&quot; {...register(&quot;email&quot;)} /&gt;
{errors.email &amp;&amp; &lt;p&gt;Email est requis&lt;/p&gt;}
&lt;/div&gt;
&lt;div&gt;
&lt;InputSelect
label={&quot;Role&quot;}
error={errors.role?.message}
options={options}
required
{...register(&quot;role&quot;)}
/&gt;
{errors.role &amp;&amp; &lt;p&gt;R&#244;le est requis&lt;/p&gt;}
&lt;/div&gt;
&lt;button type=&quot;submit&quot;&gt;Envoyer&lt;/button&gt;
&lt;/form&gt;
);
};
export default App;

答案1

得分: 2

`react-select`库没有返回实际的输入元素,而`react-hook-form`依赖于这个。您可以使用类似以下的伪事件解决这个问题:

    let pseudoEvent = { target: { name: "role", value: event.value } };

    onChange(pseudoEvent);

为了更好地理解react-select对普通的`<input />`做了什么,请拦截您的`email`输入的onChange事件并分析该事件。

    const emailHandler = register('email');

    const onEmailChange = (event: any) => {
      console.log(event);
    }

    <input type="email" {...emailHandler} onChange={onEmailChange} />
英文:

The react-select library is not returning the actual input element, which is what react-hook-form relies on. You can resolve the problem using a pseudo event like this:

let pseudoEvent = { target: { name: &quot;role&quot;, value: event.value } };
onChange(pseudoEvent);

To better understand what react-select does with a normal &lt;input /&gt;, intercept your email input onChange and analyze the event.

const emailHandler = register(&#39;email&#39;);
const onEmailChange = (event: any) =&gt; {
console.log(event);
}
&lt;input type=&quot;email&quot; {...emailHandler} onChange={onEmailChange} /&gt;

答案2

得分: 0

如果你想手动控制并调用 RHF 的 onChange 来获取 React Hook Form 的所有属性,比如字段名称(如 field),请确保在你的输入中使用类似 {...other} 的属性。这样,react-select 的 onChange 将返回选定的对象,你可以在 React Hook Form 中获取它。如果以这种方式格式化调用 field.onChange,你的输入将不会获得任何正确的属性。

英文:

react-select onChange return selected object and you react hook form can get that if you use prop like {...other} for your input.
if you want control that manually and call rhf onChange get react hook form all props as name like field and call field.onChange in this format your input didn't get any correct props

huangapple
  • 本文由 发表于 2023年2月13日 23:25:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75437898.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定