const [age, setAge] = React.useState('Assigned');
const handleChange = (event) => {
setAge(event.target.value);
console.log(age)
};
return (
<>
{
actionItemArray.map(item => (
<tr className={styles.styledTable}>
<td className={styles.styledTd}>{item.TITLE}</td>
<td className={styles.styledTd}>{item.P_PK}</td>
<td className={styles.styledTd}>
<Select
value={age}
onChange={handleChange}
>
<MenuItem value='Assigned'>Assigned</MenuItem>
<MenuItem value='Processing'>Processing</MenuItem>
<MenuItem value='Done'>Done</MenuItem>
</Select>
</td>
<td className={styles.styledTd}>{getUnixTime(item.START_DATE)}</td>
<td className={styles.styledTd}>{getUnixTime(item.DUE_DATE)}</td>
<td className={styles.styledTd}>{item.owner.FIRST_NAME item.owner.LAST_NAME}</td>
<td className={styles.styledTd}><a className={styles.styledATag}>상세보기</a></td>
<td className={styles.styledTd}><a className={styles.styledATag}>수정</a></td>
<td className={styles.styledTd}><a className={styles.styledATag} onClick={openDeleteModal}>삭제</a></td>
</tr>
))
}
</>
)
}
Hey guys. This is my code. I'm using a Material-UI Select Form tag but can't figure out how to make this form work individually while I'm using .map() method.
After I render with this code,
This looks like working fine but the Selects Forms are working at the same time. Need some guidance.
CodePudding user response:
You just have one age
state variable and you are referencing all your Select
elements to that variable. Of course whenever it changes, all of your elements are getting affected by it. What you need to do is maintain separate variables for every single Select
element in your list.
So instead of having one static value for age, let's initialise it as an object so that that we can hold value for every list item.
const [age, setAge] = React.useState({});
The idea here is to hold age in this variable against each actionItemArray element. so your state variable should look something like this:
age = {
zz: "Processing",
aa: "Done",
cc: "Assigned"
}
Of course if you have access to some unique ID, please use that as a key inside this state variable. For now I will be using item.TITLE
as the key.
This will change the way in which you were setting the state value. Earlier you were directly assigning a string to a single variable, now you will have to update your handleChange
so that it can target a specific value to save inside your object:
const handleChange = (event, title) => {
setAge({
...age,
title: event.target.value
};
console.log(age)
};
The next thing that naturally changes is the way you were accessing the state value in your Select
element. Instead of directly accessing age
, you will now have to access the specific title inside age
<Select
value={age[item.TITLE]}
onChange={(event) => handleChange(event, item.TITLE)}
>
This should be enough to get your code up and running. However something else that I suspect you want is to have a default value of "Assigning" when nothing is selected in the Select
tag. As of now when I initialised the age
variable, I set it as an empty object {}
. This would mean that no default value is provided to any Select element, and hence undefined
will show up as the default value for each element in list. To fix this, you can use an useEffect
hook to initialise all the values inside this variable as "Assigning"
useEffect(() => {
setAge(actionItemArray.map(item => age[item.title] ? age[item.title] : "Assigning"))
}, [actionItemArray])
Effectively, your final code should look something like this:
const [age, setAge] = React.useState({});
const handleChange = (event, title) => {
setAge({
...age,
title: event.target.value
};
console.log(age)
};
useEffect(() => {
setAge(actionItemArray.map(item => age[item.title] ? age[item.title] : "Assigning"))
}, [actionItemArray])
return (
<>
{
actionItemArray.map(item => (
<tr className={styles.styledTable}>
<td className={styles.styledTd}>{item.TITLE}</td>
<td className={styles.styledTd}>{item.P_PK}</td>
<td className={styles.styledTd}>
<Select
value={age[item.TITLE]}
onChange={(event) => handleChange(event, item.TITLE)}
>
<MenuItem value='Assigned'>Assigned</MenuItem>
<MenuItem value='Processing'>Processing</MenuItem>
<MenuItem value='Done'>Done</MenuItem>
</Select>
</td>
<td className={styles.styledTd}>{getUnixTime(item.START_DATE)}</td>
<td className={styles.styledTd}>{getUnixTime(item.DUE_DATE)}</td>
<td className={styles.styledTd}>{item.owner.FIRST_NAME item.owner.LAST_NAME}</td>
<td className={styles.styledTd}><a className={styles.styledATag}>상세보기</a></td>
<td className={styles.styledTd}><a className={styles.styledATag}>수정</a></td>
<td className={styles.styledTd}><a className={styles.styledATag} onClick={openDeleteModal}>삭제</a></td>
</tr>
))
}
</>
)
CodePudding user response:
You can pass the index of the item from the map function like this:
actionItemArray.map((item,i) => (
<tr className={styles.styledTable}>
<td className={styles.styledTd}>{item.TITLE}</td>
<td className={styles.styledTd}>{item.P_PK}</td>
<td className={styles.styledTd}>
<Select
value={age[i]} // to get the current age value
onChange={(e) => handleChange(e,i)}
>
<MenuItem value='Assigned'>Assigned</MenuItem>
<MenuItem value='Processing'>Processing</MenuItem>
<MenuItem value='Done'>Done</MenuItem>
</Select>
</td>
<td className={styles.styledTd}>{getUnixTime(item.START_DATE)}</td>
<td className={styles.styledTd}>{getUnixTime(item.DUE_DATE)}</td>
<td className={styles.styledTd}>{item.owner.FIRST_NAME item.owner.LAST_NAME}</td>
<td className={styles.styledTd}><a className={styles.styledATag}>상세보기</a></td>
<td className={styles.styledTd}><a className={styles.styledATag}>수정</a></td>
<td className={styles.styledTd}><a className={styles.styledATag} onClick={openDeleteModal}>삭제</a></td>
</tr>
In the handleChange
function you use that index to change the value of that particular item only and you need to set the initial value of age
to an empty array like this:
const [age,setAge] = React.useState([]);
const handleChange = (event,index) => {
setAge([...age.map((data,i) => i === index ? event.target.value:data )]);
};