I have a dropdown component where I am trying to set a localStorage value to the option that is selected from the dropdown.
const [userLanguage, setUserLanguage] = useState('en');
useEffect(() => {
localStorage.setItem("userLanguage", userLanguage ? userLanguage : '')
}, [userLanguage]);
return (
<select>
<option onClick={?}>one</option>
<option onClick={?}>two</option>
</select>
);
I am really confused on how to handle the onClick event that would set the selected option the the localStorage.
I have been able to find solutions that are somewhat related, but not that show examples for React, and specifically using hooks.
Any help would really be appreciated.
I would bind to the onChange event listener instead. The click event of option elements in single-select select elements is notoriously fragile. In your case, change your code to something like:
const [userLanguage, setUserLanguage] = useState('en');
useEffect(() => {
localStorage.setItem("userLanguage", userLanguage ? userLanguage : '')
}, [userLanguage]);
return (
<select onChange={(e) => setUserLanguage(e.target.value)}>
<option value="one">one</option>
<option value="two">two</option>
</select>
);
I added value attributes to your options only in an abundance of caution; by default the value of the select will gain the text of the option if the value is not explicitly set.
I should point out that older questions have pointed out the fragility of the click event on option elements. In particular, the answers to the question getting an onclick event to a select option using js by Vad.Gut explain the situation well.
Related
I've got an Address react component which contains an address object defined by {streetAddress, additionalStreetAddress, city, jurisdiction, zipCode}.
Within the JSX I have jurisdiction as a dropdown Select of all the US states.
<Select
id={`${id}-jurisdiction`}
name="jurisdiction"
placeholderOption=" "
labelVisual="State"
value={jurisdiction}
>
{JURISDICTIONS.map((currentJurisdiction) => (
<SelectOption
id={`jurisdiction-${currentJurisdiction}`}
key={currentJurisdiction}
value={currentJurisdiction}
onClick={(e) => { jurisdiction = e.currentTarget.value; }}
>
{currentJurisdiction}
</SelectOption>
))}
</Select>
As you can see, onClick is setting address.jurisdiction to the selected option (i.e. the selected state).
In my test suite I am trying to test that this works by using the following test:
it('should update selected option and updated address jurisdiction when user makes a selection', async () => {
const jurisdictionDropDown = screen.getByRole('combobox');
const user = userEvent.setup();
const selectedJurisdiction = 'MA';
await user.selectOptions(jurisdictionDropDown, [selectedJurisdiction]);
expect(address.jurisdiction).toEqual('MA');
});
The issue I'm seeing is jest is expecting 'MA' but receiving an empty string. Is jurisdiction not being set, or am I referencing it wrong in the expect statement?
From the code, and the fact that you used the word "var" to describe your problem, it sounds like you are setting a normal variable rather than setting and keeping track of state.
Normally, in React you use state to keep track of values changing between renders, otherwise they get lost and you end up with the same initial values. You need to use the useState hook and use that to keep track of your state which hopefully will hopefully make the test pass (assuming it is written correctly).
import React, { useState } from 'react';
const [jurisdiction, setJurisdiction] = useState(JURISDICTIONS[0]);
<Select
id={`${id}-jurisdiction`}
name="jurisdiction"
placeholderOption=""
labelVisual="State"
value={jurisdiction}
>
{JURISDICTIONS.map((currentJurisdiction) => (
<SelectOption
id={`jurisdiction-${currentJurisdiction}`}
key={currentJurisdiction}
value={currentJurisdiction}
onClick={(e) => setJurisdiction(e.currentTarget.value)}
>
{currentJurisdiction}
</SelectOption>
))}
</Select>
I have trouble with the Select field.
When I use the watch on select HTML attribute and change options in it, it doesn't re-render in the console. it stays the same, but when I use onChange, its re-renders.
My example of code --->
const example = watch('skills')
console.log(watch('skills'))
console.log(example)
<select {...register( 'skills')}>
<option>1</option>
<option>2</option>
</select>
when I choose option 2, it doesn't show option 2. what should I do? thanks
React hook form does not work with select forms correctly (no optimization).
Try the following:
const watchShowAge = watch('primaryType');
...
{ watchShowAge === 10 && (<p>You are too young!</p>) }
I have a select:
<Select classNamePrefix="select" ref={myRef} menuPortalTarget={document.body} styles={style} placeholder="Select Foods" name="Foods" value={inputField.foods} options={options} onChange={event => handleInputChange2(index, event)} className="select selectNarrow" />
const handleInputChange2 = (index, event) => {
const values = [...inputFields];
values[index] = event;
setInputFields(values);
console.log(event);
};
Whereby {options} are built from a collection. On this same page I can add to this collection - after adding a new item and then opening the select it is not immediately visible until after I have chosen an already existing item. How do I get the React-Select to refresh the list each time I open it (rather than an onChange)
I feel like we're missing some code to properly answer your question. How did you add a 'new item'? While you added to the collection, did you also update your options array?
Displayed options are controlled by the options prop. If you add a new option to this array, React-Select will rerender and the new option would be available.
I am still a novice in React Js and recently I have been developing using PrimeReact. The Forms and DataTables are doing well for me but I cant seem to figure out how deal with the Dropdown. My state is managed by redux and after mapStateToProps I and loading my data using componentDidMount I can console.log and see my data array. With a normal react select input I have been using the following code:
const {accounttypes} = this.props;
console.log(accounttypes)
let typesOptions = accounttypes.length > 0
&& accounttypes.map((item, index) => {
return (
<option key={item.id } value={item.id}>{item.name}</option>
)
}, this);
This works as an option as I can post to my backend. However I would want to use PrimeReact for all my forms and I have been struggling on how to go about it. The following has been my attempt and its giving me a headache:
<div className="p-field p-col-12 p-md-4">
<Dropdown
value={account_type}
optionValue = {accounttypes.id}
optionLabel = {accounttypes.name}
options={accounttypes}
onChange={this.onTypeChange}
placeholder="Select an Acco"
autoFocus = {true}
editable={true}
/>
</div>
account_type is the name of my field and my django model references the accountytpe model and would like to capture account_type whilst creating an Account. May someone help. And thanks in advance
optionLabel and optionValue should point to equivalent properties of your object. In your case I guess the correct way is this
optionValue="id"
optionLabel="name"
I am using react redux form Fields and I have drop down of classes. I am able to select any class from drop down.
but the issue is that whenever I select any value (class) from drop down I want to trigger action onChange. When I trigger action with on change drop down values does not set and it does not show selected value.
I am using following lines of code
<Field name="class._id" component="select" className="form-control" onChange={this.onChange.bind(this)} >
<option value="">Select class...</option>
{this.props.classes.map(Class =>
<option value={Class._id} key={Class._id} >{Class.name}</option>)}
</Field>
here is onChange function
onChange(){
console.log(" Triggered")
}
If I do not set onChange event my drop down works correctly and it shows selected value correctly with proper text.
but I want to call function whenever use select any value
Can you give more context for this code, perhaps putting the whole component (and any modules or containers or whatever) in a JSBin or Fiddle? That will help SO posters better know how to help you. That said, it looks like your code is correct. You can get the value out of the select kind of like this:
onChange(event) {
console.log(event.target.value);
}
Does that help?
May be you should better use fields prop of redux and standard html elements?
const {fields} = this.props
<select {...fields.class} onChange={this.handleChange}>
...
handleChange(event) {
// do your stuff
this.props.fields.class.onChange(event)
}