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

问题描述 投票:0回答:9

我正在使用react-hook-forms控制器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}
              />
            }
          />

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

  const handleCategoryInputChange = newValue => {
    return setValue('businessCategory', newValue, true);
  };

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

{
  fullName: "DJ service"
  id: "gcid:dj"
  name: "DJ service"
  publisher: "GMB"
}

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

reactjs react-select react-hook-form
9个回答
58
投票

按以下方式更新您的代码

在您的导入中

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

在你的钩子组件中

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>
    )
}

19
投票

对于多选(与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
    />
  )}
/>

7
投票
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
        />
        )}
/>

6
投票

好吧,实际上大多数答案不适用于您有自定义 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>}

5
投票

我让它像这样工作:

const options = [
    {value: '', label: ''}
]
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>

2
投票

我想发布对我有用的内容。我使用了 react-selectreact-hook-form@hookform/error-message:

我创建了一个函数如下

  const handleCategoryInputChange = (newValue: any) => {
    console.log(newValue.value);
    return setValue('contract', newValue.value);
  };

我的反应选择如下所示:

<Controller
  name="contract"
  control={control}
  rules={{ required: true }}
  render={({ field: { onChange, value, name, ref } }) => (
    <ReactSelect
     // value={contractData.find((c) => c.value === value)}
     // onChange={(val) => onChange(val)}
     onChange={handleCategoryInputChange}
     options={contractData}
     ref={ref}
     name={name}
     defaultValue={contractData[0]}
     theme={customTheme}
     isSearchable={false}
     className="block w-full min-w-0 flex-1 sm:text-sm"
/>
)}
/>
<ErrorMessage errors={errors} name="contract" message="Select a Contract" />

我认为我的 className 无法正常工作,您可以忽略该部分。不过它适用于我的特定设置,哈哈。注释掉的代码没有按照我想要的方式工作,因为当我控制台记录数据时,我得到的数据如下:

contract: {label: 'contract name', value: 'contract name'}
optionPeriods: "dfd"
performanceEndDate: "2022-12-08"
performanceStartDate: "2022-12-08"
proposalDueDate: "2022-12-08T12:54"
requirements: "dfd"
trackingNumber: "dfd"

所以我注释掉了该特定解决方案,并按照您现在看到的方式进行操作,我得到了合同所需的确切数据,如下所示:

contract: "contract name"
optionPeriods: "dfd"
performanceEndDate: "2022-12-08"
performanceStartDate: "2022-12-08"
proposalDueDate: "2022-12-08T12:54"
requirements: "dfd"
trackingNumber: "dfd"

我希望这有帮助


1
投票

对我有用的是:

  • react-hook-form v7.45.2
  • 反应选择5.7.4
import { useForm, SubmitHandler, Controller } from "react-hook-form"

const { register } = useForm();

const options = [
    { value: 'chocolate', label: 'Chocolate' },
    { value: 'strawberry', label: 'Strawberry' },
    { value: 'vanilla', label: 'Vanilla' }
]

return (
    <Controller
        control={control}
        defaultValue='give_it_a_default'
        name="give_it_a_name"
        rules={{ required: true }}
        render={({ field, value, name, ref }) => (
            <Select
                name={field.name}
                inputRef={field.ref}
                options={options}
                value={options.find((c) => c.value === field.value)}
                onChange={val => field.onChange(val.value)}
            />)
      )}
    />
)

0
投票

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

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


0
投票

使用

register
代替:

const { control, handleSubmit, setValue, register } = useForm();
register('Control_name');
<Select
  options={options}
  onChange={(selected: any) => {
    if (selected) {
      setValue('Control_name', selected.value);
    }
  }}
/>
© www.soinside.com 2019 - 2024. All rights reserved.