Using react-select with redux form - reactjs

I am trying to use react-select with redux-form. My code is as follows:
const DropdownComponent = ({
input, options, name, id, placeholder,
}) => (
<Select
id={id}
name={name}
placeholder={placeholder}
value={input.value}
options={options}
onChange={input.onChange}
onBlurResetsInput={false}
onCloseResetsInput={false}
{...input}
onBlur={() => input.onBlur(input.value.value)}
/>
);
The options that I am sending is as:
const options = [
{ value: '1', label: '%' },
{ value: '2', label: '$' },
];
This works fine when I select a value, but the moment the select loses focus, the value is cleared onBlur. Any suggestions as to what am I missing here?

I suspect this maybe the culprit: onBlur={() => input.onBlur(input.value.value)}
I think that extra .value is undefined.

Related

Render Name and id Autocomplete material UI

i'm working with Autocomplete MUI, i want to render name and id same time in-line but it render name only, can u guys help me, thank you so much
export const zoneUserId = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
];
const listZoneId = {
options: zoneUserId,
getOptionLabel: (option: IZoneID) => option.name,
};
<Autocomplete
{...listZoneId}
id="zoneUserId"
includeInputInList
renderInput={params => (
<TextField {...params} label="User ID" variant="standard" />
)}
/>
You may have to change the getOptionLabel. Either concatenate or try like this
getOptionLabel: (option: IZoneID) => `${option.id} - ${option.name}`

How can I get option value from react select?

My codes are as below, can you help me? Where am I doing wrong?
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const { register, handleSubmit, watch, formState: { errors }, control } = useForm();
const onSubmit = (data, e) => {
e.preventDefault();
console.log(data);
}
I want to get the option data using react select, but the defaltvalue is coming, I can't get the option data at all.
<Controller
name='stocktype'
render={({ register, value }) => (
<Select
{...register}
options={options}
styles={customStyles}
noOptionsMessage={() => 'Aramanıza uygun değer bulunamadı'}
placeholder={'Stok Tipi Seçiniz'}
value={options.find((c) => c.value === value)}
/>
)}
control={control}
defaultValue={options[0]}
/>
You'll need to grab the controller's hooks and pass them to the Select component in order to execute the correct events to grab the data.
Do something like this:
<Controller
control={control}
name="test"
render={({
field: { onChange, onBlur, value, name, ref },
register
}) => (
<Select
{...register}
options={options}
styles={customStyles}
noOptionsMessage={() => 'Aramanıza uygun değer bulunamadı'}
placeholder={'Stok Tipi Seçiniz'}
value={value}
onChange={onChange} // send value to hook form
onBlur={onBlur} // notify when input is touched
/>
)}
/>
Notice the field attribute under render and how hooks are passed to the Select.

React-Select --- How to get default value and overwrite the default value when user selected another option

Below is my react-select, field.value is the value that return from API.
For example, field.value is 'Active'.
So, my frontend will show 'Active' and this is what I want, but if I select another option which is 'Inactive', it wont change the value and keep displaying the option 'Active'.
My question is how to change the default value('Active') to another selected value('Inactive')?
Thanks
const methods = useFormContext();
const [selectedOption, setSelectedOption] = useState("none");
const options = [
{ value: 'Active', label: 'Active' },
{ value: 'Inactive', label: 'Inactive' }
]
const handleTypeSelect = e => {
setSelectedOption(e.value);
};
return (
<div>
<Controller
name="inventory_source_status"
control={control}
render={({ field }) => (
<Select
{...field}
id="inventory_source_status"
className="mt-8 mb-16"
placeholder="Inventory Source Status *"
options={options}
onChange={handleTypeSelect}
value = {{ value: field.value, label: field.value } || ''}
required
error={!!errors.inventory_source_status}
helperText={errors?.inventory_source_status?.message}
/>
)}
/>
</div>
);
You should use
defaultValue={{ value: field.value, label: field.description}}

How to get value from react-select in a functional component React

I am making use of react-select for the first time in a form. I am having issues getting the value from the select input and send it via Axios to backend.
const options=[
{ value: 'Telecomms', label: 'Telecomms' },
{ value: 'Construction', label: 'Construction' },
{ value: 'Manufacturing', label: 'Manufacturing' },
]
function Register(props) {
const [newUser,getUser]=useState({
name: "",
businessSector:"",
})
const dispatch = useDispatch()
// onChange handler
const changeHandle=e=>{
getUser({
...newUser,
[e.target.name]:e.target.value
})
}
const SubmitHandle=e=>{
e.preventDefault()
console.log(newUser)
if (newUser) {
dispatch(registerUser(newUser))
}
}
return (
<FormDialog
loading={isLoading}
onClose={onClose}
open
headline="Registration"
onFormSubmit={SubmitHandle }
hideBackdrop
hasCloseIcon
content={
<Fragment>
<Grid Container spacing={20}>
<TextField
variant="outlined"
margin="normal"
name="name"
value={newUser.name}
onChange={changeHandle}
required
fullWidth
label="Full name"
autoFocus
autoComplete="off"
type="text"
InputProps={{
className: classes.input
}}
FormHelperTextProps={{ error: true }}
/>
<InputLabel id="demo-simple-select-label">Business Sector</InputLabel>
<Select
value={newUser.businessSector}
onInputChange={changeHandle}
options={options}
name="businessSector"
/>
Any time i try to select an option is gives the following error
Type error: cannot read property 'name' of undefined
I am wondering where am actually getting it wrong. If I try to check the state from the dev tools, its not registering on state.
The error Type error: cannot read property 'name' of undefined comes from the use of [e.target.name] in your changeHandler. You're using the wrong prop/callback for this; instead of onInputChange use onChange:
const onChangeHandler = (change) => {
getUser({
...newUser,
businessSector: change
});
};
return (
<Select
value={newUser.businessSector}
onChange={onChangeHandler}
options={options}
/>
);
onInputChange is for when the input changes so if you were using the isSearchable prop you'd be able to type inside of the Select input and that would send the event e you're expecting to get, but because its just a select it returns an empty string instead.

Returning correct value using react-select and react-hook-form

I'm using react-hook-forms Controller api around AsyncSelect from react-select to load options as the user types from an external API. Everything works fine except the returned value is coming back as the string "[object Object]" instead of the fullName property from the object.
My component:
<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}
/>
}
/>
My handleChange function. SetValue is from react-hook-form:
const handleCategoryInputChange = newValue => {
return setValue('businessCategory', newValue, true);
};
Any my data is an array of objects with the following shape:
{
fullName: "DJ service"
id: "gcid:dj"
name: "DJ service"
publisher: "GMB"
}
Any clues on this would be appreciated, thank you!
Update your code in following way
In your import
import { useForm, Controller } from 'react-hook-form';
import Select from 'react-select';
In your hook component
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>
)
}
For multi-select (works with 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
/>
)}
/>
I made it work like this:
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>
well, actually most of these answers don't work for situations where you have a custom onChange function. The trick (seems like a bug) is to set the "onChange(val.value)" inline first and then set your state variable. Here is the full code I have that works;
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>}
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
/>
)}
/>
Fixed this by approaching it with a custom register via react-hook-form as seen here:
https://react-hook-form.com/get-started#Registerfields
I wanted to post what worked for me. I used react-select, react-hook-form, and #hookform/error-message:
I created a function as follows
const handleCategoryInputChange = (newValue: any) => {
console.log(newValue.value);
return setValue('contract', newValue.value);
};
My react select looks like this:
<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" />
I don't think my className is working properly you can ignore that part. It is working for my specific set up though lol. The commented out code did not work the way I wanted because when i console logged the data I got it as follow:
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"
so I commented out that specific solution and did it the way you see now and i get the exact data i want for my contract as you can see below:
contract: "contract name"
optionPeriods: "dfd"
performanceEndDate: "2022-12-08"
performanceStartDate: "2022-12-08"
proposalDueDate: "2022-12-08T12:54"
requirements: "dfd"
trackingNumber: "dfd"
I hope this helps

Resources