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

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.

Related

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.

setFieldValue, Formik and InvalidStateError: Failed to set the 'value' property on 'HTMLInputElement'

I'm trying to upload a file using Formik and setFieldValue.
I don't understand why i'm getting
InvalidStateError: Failed to set the 'value' property on 'HTMLInputElement': This input element > accepts a filename, which may only be programmatically set to the empty string.
When i'm uploading a file
I have some knowledge of React, but it's my first time with Formik.
Some (maybe useful) code
export const ImageUploaderField = ({ ...props }) => {
const { setFieldValue } = useFormikContext()
const [field] = useField(props)
return (
<Field
{...field}
{...props}
onChange={(event) => {
setFieldValue(field.name, event.currentTarget.files)
}}
/>
)
}
Call site
<ImageUploaderField name="filename" type="file" />
I was having the same error. Got it working by adding a value={undefined} prop to <input> element.
Instead of adding value={undefined}, ignore adding value property to Field
export const ImageUploaderField = ({ ...props }) => {
const { setFieldValue } = useFormikContext()
const [field] = useField(props)
const {value, ...rest} = field;
return (
<Field
{...rest}
{...props}
onChange={(event) => {
setFieldValue(field.name, event.currentTarget.files)
}}
/>
)
}
// set value to undefined will solve your problem
<TextField
size="small"
fullWidth
id="ticket-file"
type="file"
name="file"
label="Upload file"
value={undefined}
onChange={(event) => {
setFieldValue("file", event.currentTarget.files);
}}
onBlur={handleBlur}
accept="image/png, application/pdf, image/jpeg, image/jpg"
InputLabelProps={{
shrink: true,
}}
inputProps={{
multiple: true,
}}
error={touched.file && Boolean(errors.file)}
helperText={touched.file && errors.file}
/>

A component is changing an uncontrolled Autocomplete to be controlled

Can you tell me that why I'm getting error "A component is changing an uncontrolled Autocomplete to be controlled.
Elements should not switch from uncontrolled to controlled (or vice versa).
Decide between using a controlled or uncontrolled Autocomplete element for the lifetime of the component."
component :
function AutoComplete(props) {
const defaultProps = {
options: props.options,
getOptionLabel: option => option.name,
};
const handleChange = (e, value) => {
props.onChange(value);
};
return (
<Autocomplete
{...defaultProps}
renderInput={params => (
<TextField {...params} label={props.label} margin="normal" />
)}
onChange={handleChange}
value={props.value}
/>
);
}
calling autocomplte:
<Controller
control={control}
name = 'country'
as = {
<AutoComplete
options={countryOptions}
onChange={selectCountryHandler}
label="Country"
value={selectedCountry || ''}
/>
} />
how can I solve this error?
You ensured that the value property never had been undefined, but you had to do same for inputValue.
the "value" state with the value/onChange props combination. This state represents the value selected by the user, for instance when pressing Enter.
the "input value" state with the inputValue/onInputChange props combination. This state represents the value displayed in the textbox.
⚠️ These two state are isolated, they should be controlled independently.
Component becomes uncontrolled when inputValue property is undefined, and vice versa.
If in the following example you delete an empty string from
React.useState('') you'll get the same error message because inputValue during first render is undefined.
import React from 'react'
import TextField from '#material-ui/core/TextField'
import Autocomplete from '#material-ui/lab/Autocomplete'
const options = ['Option 1', 'Option 2']
export default function AutocompleteLab() {
const [value, setValue] = React.useState(options[0])
const [inputValue, setInputValue] = React.useState('')
return (
<div>
<div>{`value: ${value !== null ? `'${value}'` : 'null'}`}</div>
<div>{`inputValue: '${inputValue}'`}</div>
<br />
<Autocomplete
value={value}
onChange={(_, newValue) => {
setValue(newValue)
}}
inputValue={inputValue}
onInputChange={(_, newInputValue) => {
setInputValue(newInputValue)
}}
options={options}
style={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Name" variant="outlined" />}
/>
</div>
)
}
When no value is selected, you need to add || null to prevent the Autocomplete going into uncontrolled mode:
<Autocomplete {...props} value={props.value || null} />
If you pass value={undefined} to the Autocomplete component, it will start in "uncontrolled" mode, meaning it keeps its own internal state. Then if you later supply a value it raises the "A component is changing" error. But if you pass value={null}instead of value={undefined} that causes the Autocomplete to start in controlled mode. The Autocomplete will assume you will be providing the state, not keep its own, and the error goes away.
I solved this by removing the default value.
<Autocomplete
multiple
id="multiple-limit-tags"
options={(option) => option.label}
getOptionLabel={(option) => option}
// defaultValue={options || []}
renderInput={(params) => <TextField {...params} label="My Label" />}
/>
It wasn't obvious how to solve this, and the documentation doesn't help much either. I find it curious that a copy-pasted example from the documentation results in this error. I guess the example works because the choices are hard-coded.
Previous answer was absolutely correct, BUT I spend 20 minutes while I figure out that inputValue it should be value
So working example from me:
export default function AddModal(): ReactElement {
const [resource, setResource] = useState('one');
<Autocomplete
id="autocomplete"
options={['one', 'two']}
defaultValue={resource}
value={resource}
PopperComponent={StyledPopper}
onChange={(event, newInputValue) => setResource(newInputValue)}
renderInput={(params) => <TextField {...params} />}
/>
I had the same issue today, but I was able to solve it by providing a default value of null as well as providing a null value in case of it not existing. I'll leave the code that worked for me:
<Autocomplete
value={filters.tag || null}
defaultValue={null}
options={tags || []}
getOptionLabel={(option) => option}
renderInput={(params) => (
<TextField {...params} label="Search" variant='outlined' size='small' />
)}
fullWidth
onChange={(event, value) => {
if (value) {
setFilters({ ...filters, tag: value });
} else {
setFilters({ ...filters, tag: '' });
}
}}
/>
For me I fixed this issue by updated the onChange function and add || null rather then removing the default value since I still need it here is the code
<Box mt={2}>
<Controller
control={control}
name="thematic"
rules={{
required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange } }) => (
<Autocomplete
defaultValue={
questionData?.thematic ? questionData?.thematic : null
}
options={thematics}
getOptionLabel={(option) => option.name}
onChange={(event, values) => {
onChange(values || null)
}}
renderInput={(params) => (
<TextField
{...params}
label="Thématique"
placeholder="Thématique"
helperText={errors.thematic?.message}
error={!!errors.thematic}
/>
)}
/>
)}
/>
</Box>
For the autocomplete with options which is a simple array without object you can simply do it that way and u want get any issue
<Box mt={2}>
<Controller
control={control}
name="type"
rules={{
required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange, value } }) => (
<Autocomplete
freeSolo
options={['Champ', 'Sélection', 'Choix multiple']}
onChange={(event, values) => onChange(values)}
value={value}
renderInput={(params) => (
<TextField
{...params}
label="Type de la question"
variant="outlined"
onChange={onChange}
helperText={errors.type?.message}
error={!!errors.type}
/>
)}
/>
)}
/>
</Box>
the default value you can set it within useForm if you are using react-hook-form
const {
handleSubmit,
control,
watch,
register,
formState: { errors },
} = useForm({
defaultValues: {
...
type: questionData?.type ? mapperQuestionType[questionData?.type] : '',
},
})

How to use React Hook Form with RNPickerSelect in React Native?

I am trying to use RNPickerSelect (https://github.com/lawnstarter/react-native-picker-select) with react-hook-form in React Native. I've tried with Controller wrapper to use RNPickerSelect component. And it always invokes 'required' error. Could someone please point me to right direction? Here is my code.
const CategoryContentView = () => {
const tempData = [];
categories.forEach((data) => {
tempData.push({ label: `${data.name}`, value: `${data.id}` });
});
return (
<>
<Controller
as={
<RNPickerSelect
onValueChange={(value) => {
setCategory(value);
}}
items={tempData}
/>}
rules={{
required: true,
}}
control={control}
name="category"
valueName="value"
onChange={([value]) => value}
error={!!get(errors, 'category')}
/>
{errors.category && <ErrorView errors={['this is required']} />}
</>
};
Thank you in advance
I'm probably late but here is the example:
<Controller
render={({onChange, ...props}) => {
<RNPickerSelect
{...props}
onValueChange={(value) => {
onChange(value);
}}
items={tempData}
/>
}}
rules={{
required: true,
}}
control={control}
name="category"
valueName="value"
error={!!get(errors, "category")}
/>;
So, render prop is actually a function that has a couple of parameters and onChange is one of them. This method should be called every time you want to update your value and that's why I called it inside a onValueChange as you can see it in the example.

How to use onchange with autocomplete material ui?

With the method handleChange is handled OnChange event of the Form Input with Hooks style that set the state off the object.
The handleChange function in turn calls setLocation which updates the location state with the new value.
To make user data entry easier, I decided to change the city field to an autocomplete, but I failed to capture the value of the autocomplete.
In the documentation he tells me that I need to pass two arguments but I can't understand very well
function(event: object, value: any) => void
event: The event source of the callback
value: null
How can I access the value of the field and put it into my function to insert the data?
<Autocomplete
style={{ width: 300 }}
value={location.City}
onChange={handleChange}
options={list.City}
classes={{
option: classes.option,
}}
autoHighlight
getOptionLabel={option => typeof option === 'string' ? option : option.City}
renderOption={option => (
<React.Fragment>
{option.City} -{option.State}
</React.Fragment>
)}
renderInput={params => (
<TextField {...params} label="City" value={location.City} margin="normal" variant="outlined" style={{ width: 220 }} inputProps={{
...params.inputProps,
autoComplete: 'disabled', // disable autocomplete and autofill
}}/>
)}
/>
If you're just trying to get the value of the input as the user types, you need to use onInputChange. The onChange handler runs when the user selects an option from the drop down.
export default function ComboBox() {
function handleInputChange(event, value) {
console.log(value);
}
return (
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionLabel={(option: FilmOptionType) => option.title}
style={{ width: 300 }}
onInputChange={handleInputChange}
renderInput={params => (
<TextField {...params} label="Combo box" variant="outlined" fullWidth />
)}
/>
);
}
Codesandbox
the react SyntheticEvent set null target in an Asynchronous requests, try to use
event.persist()
on the event
https://reactjs.org/docs/events.html#event-pooling
const handleOnChangeText=(event)=> {
event.persist();
console.log(event)
let active = true;
setOpen(true);
if (!loading) {
return undefined;
}
(async () => {
const response = await fetch('https://country.register.gov.uk/records.json?page-size=5000');
await sleep(1e3); // For demo purposes.
const countries = await response.json();
if (active) {
setOptions(Object.keys(countries).map(key => countries[key].item[0]) as CountryType[]);
}
active = false;
})();
}
<Autocomplete
id="comboboxAsync"
disableOpenOnFocus
style={{ width: 300 }}
open={open}
onInputChange={handleOnChangeText}
...
Id is getting retrieved under this pattern: id-option-numberOfOption, that's why I had to split the retrieved value in order to update the state
const handleAutoCompleteChange = (event, value) => {
this.setState({ ...this.state, [event.target.id.split("-")[0]]: value });
console.log([event.target.id.split("-")[0]],value);
}
You can use mui-autocomplete npm its easy and less coding with more options(Like avatar view asynchronus calls).You should try it out. Here is the example for more info visit here.
[http://mui-autocomplete.com/home]
`import React from 'react';
import MuiAutocomplete from 'mui-autocomplete';
const cities = [
{
id: 1,
name: "Alabama",
code: "AL"
},
{
id: 2,
name: "Alaska",
code: "AK"
},
{
id: 3,
name: "American Samoa",
code: "AS"
}];
function Home () {
return (
<div>
<MuiAutocomplete
placeholder="Countries"
name="countries"
setvalue={1}
setdata={cities}
variant="outlined"
template={{
title: 'name'
}}
/>
</div>
);
}`

Resources