英文:
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 "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;
答案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: "role", value: event.value } };
onChange(pseudoEvent);
To better understand what react-select does with a normal <input />
, intercept your email
input onChange and analyze the event.
const emailHandler = register('email');
const onEmailChange = (event: any) => {
console.log(event);
}
<input type="email" {...emailHandler} onChange={onEmailChange} />
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论