Reputation: 361
I mapping over data which displays different select option dropdowns. I need my onChange function to be on the select tag to capture the selected option, but the select tag is before the function is initialized so I'm not sure how to go about passing the function into it.
<select onChange={onChange}> <--- onChange function cant be passed here
{options.map((attribute) => {
function onChange(event) {
const newSelected = { ...selected };
newSelected[attribute.title] = event.target.value
}
return (
<option value={attribute.index}>{attribute.value}</option>
)
})}
</select>
Upvotes: 0
Views: 68
Reputation: 1074495
Define your onChange
so that it uses the information on the event object it receives to find the right entry in the list, something like this:
<select onChange={event => {
const attribute = options[event.currentTarget.value];
const newSelected = {
...selected,
[attribute.title]: event.currentTarget.value,
};
// ...
}}>
{options.map((attribute, index) => {
return (
<option key={attribute.value} value={index}>{attribute.value}</option>
)
})}
</select>
It's hard to be sure the details of that are right without knowing the structure of options
or what you want newSelected
to be, but I think I've mostly inferred it from the question's code. Note that I changed attribute.index
to index
in the map
call, and that I added a key
(you need key
on any array you render), assuming that attribute.value
is unique.
That said, if attribute.value
is unique, I think I'd use it instead of index
or attribute.index
:
<select onChange={event => {
const attribute = options.find(({value}) => value == event.currentTarget.value);
const newSelected = {
...selected,
[attribute.title]: attribute.index,
};
// ...
}}>
{options.map(({value}) => {
return (
<option key={value} value={value}>{value}</option>
)
})}
</select>
Upvotes: 1
Reputation: 13902
I think I sort of see why you're doing it the way you're doing it, so let me try to address how to handle it differently:
First of all, you're doing it because the onChange
function needs access to the attribute.title
value. So for you, you're thinking the easiest way to get that value is to define the function in the .map
function, where you have access to each individual attribute as it's coming through.
You can't, though. As I said in my comment: It conceptually doesn't make sense. <select onChange={onChange}>
implies a singular onChange
function, but you're defining a new onChange
function in every iteration of .map
.
So what you need to do is define onChange
before your render
function, and then inside that you have to find the matching attribute
inside the options
array, so that you can then use attribute.title
as you like.
[edit] TJ Crowder gives a specific code example of how to do that.
Upvotes: 1