使用 react-select 和 react-hook-form 返回正确的值

gee*_*rry 9 reactjs react-select react-hook-form

我正在使用 react-hook-forms Controller api 围绕来自 react-select 的 AsyncSelect 加载选项,因为用户从外部 API 键入。一切正常,除了返回的值作为字符串"[object Object]"而不是对象的 fullName 属性返回。

我的组件:

           <Controller
            control={control}
            name="businessCategory"
            as={
              <AsyncSelect
                className="react-select-container"
                loadOptions={v => handleAutocompleteLookup(v)}
                onChange={handleCategoryInputChange}
                getOptionLabel={option => option.name}
                getOptionValue={option => option.fullName}
              />
            }
          />
Run Code Online (Sandbox Code Playgroud)

我的 handleChange 函数。SetValue 来自 react-hook-form:

  const handleCategoryInputChange = newValue => {
    return setValue('businessCategory', newValue, true);
  };
Run Code Online (Sandbox Code Playgroud)

我的任何数据都是具有以下形状的对象数组:

{
  fullName: "DJ service"
  id: "gcid:dj"
  name: "DJ service"
  publisher: "GMB"
}
Run Code Online (Sandbox Code Playgroud)

任何有关这方面的线索将不胜感激,谢谢!

小智 18

对于多选(与react-hook-form v7一起使用):

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

const {
  control
} = useForm();

<Controller
  control={control}
  defaultValue={options.map(c => c.value)}
  name="options"
  render={({ field: { onChange, value, ref }}) => (
    <Select
      inputRef={ref}
      value={options.filter(c => value.includes(c.value))}
      onChange={val => onChange(val.map(c => c.value))}
      options={options}
      isMulti
    />
  )}
/>
Run Code Online (Sandbox Code Playgroud)


Mal*_*y M 16

按以下方式更新您的代码

在您的进口

import { useForm, Controller } from 'react-hook-form';
import Select from 'react-select';
Run Code Online (Sandbox Code Playgroud)

在您的钩子组件中

function Yourcomponent(props){

    const methods = useForm();
    const { handleSubmit } = methods;
    

    const options = [
     { value: '1', label: 'Apple'},
     { value: '2', label: 'Ball'},
     { value: '3', label: 'Cat'},
    ];
    
    const default_value = 1; // you can replace with your default value
    

    // other codes of the component 
    

    function submitHandler(formData){
    
    // values are available in formData

    }


    return(
      <div>
        
        {* other part of your component *}
        <form onSubmit={handleSubmit(submitHandler)} >

           {* other part of your form *}
            <Controller
                control={methods.control}
                defaultValue={default_value}
                name="field_name_product"
                render={({ onChange, value, name, ref }) => (
                    <Select
                        inputRef={ref}
                        classNamePrefix="addl-class"
                        options={options}
                        value={options.find(c => c.value === value)}
                        onChange={val => onChange(val.value)}
                    />
                )}
            />

           {* other part of your form *}
        </form>

        {* other part of your component *}
      </div>
    )
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案对我来说 onChange 函数有一个问题 - 修复它的是使用 `render={({ field })` ,然后在 `onChange` 属性上使用 `onChange={val =&gt; field.onChange(val.value) )}`。也许我使用的是更新版本的react-hook-form,但是onChange现在是字段对象的属性。 (8认同)
  • 这是一个对我有用的例子。谢谢。 (2认同)
  • 你可以直接选择 ref={ref} (2认同)

小智 6

import Select from "react-select";
import { useForm, Controller } from "react-hook-form";
const options = [
     { value: '1', label: 'Apple'},
     { value: '2', label: 'Ball'},
     { value: '3', label: 'Cat'},
    ];
const {control} = useForm();
<Controller
 control={control}
 name="AnyName"
 render={({ field: { onChange, value, name, ref } }) => (
        <Select
        inputRef={ref}
        classNamePrefix="addl-class"
        options={options}
        value={options.find((c) => c.value === value)}
        onChange={(val) => onChange(val.map((c) =>c.value))}
        isMulti
        />
        )}
/>
Run Code Online (Sandbox Code Playgroud)


小智 5

我让它像这样工作:

const options = [
    {value: '', label: ''}
]
Run Code Online (Sandbox Code Playgroud)
import { useForm, Controller } from "react-hook-form";

import { ErrorMessage } from "@hookform/error-message";

import Select from "react-select";


const methods = useForm();


<section>
    <label>Label</label>

    <Controller
      as={Select}
      name="Name"
      options={options}
      isMulti
      control={methods.control}
    />

    <ErrorMessage errors={methods.errors} name="Name" />
</section>
Run Code Online (Sandbox Code Playgroud)

  • 它在控制器上抛出“TypeError: props.render is not a function” (9认同)

Can*_*mak 5

好吧,实际上大多数答案不适用于您有自定义 onChange 函数的情况。技巧(似乎是一个错误)是先内联设置“onChange(val.value)”,然后设置状态变量。这是我有效的完整代码;

 import { useForm, Controller } from "react-hook-form";
   const {
       register,
       control,
       formState: { errors },
       handleSubmit,
    } = useForm();

   const handleChangeType = (option) => {
      setItemType(option);
      var options = getOptions(option.value); 
      setList(options);
      setGender(null);
   }; 

    <Controller
      control={control}
      name="itemType"
      rules={{
         required: {
            value: assetType.value == "item",
            message: "Item type is required.",
         },
      }}
      render={({ field: { onChange, value, ref, name } }) => (
         <Select 
            className={"react-select"}
            classNamePrefix={"react-select"}
            placeholder={"Item type"} 
            options={itemTypeList}  
            onChange={val => {
                onChange(val.value);
                handleChangeType(val); 
            }} 
         />
      )}
   /> 
   {errors.item?.message && <div class="validationText">{errors.item?.message}</div>}
Run Code Online (Sandbox Code Playgroud)


gee*_*rry 0

通过react-hook-form使用自定义寄存器来解决这个问题,如下所示:

https://react-hook-form.com/get-started#Registerfields