Reputation: 222
i am using table input field to update state under map function to render it according to number of elements in the state.But when I used value={item.account} values are not updated in the state.which works fine when I use **value={accountCounter.account} where accountCounter is reactjs hook of type
const[accountCounter,setAccountCounter]=useState([
{ id: 1, account:"" ,accountOwner:""},
{ id: 2, account: "hi",accountOwner:"" },
{ id: 3, account: "bu" ,accountOwner:""}
And here is my rendering function
accountCounter.map((item,key)=>{
return(
<tr key={key}>
<td><input type="text" value={item.account}
name="account" onChange={(e)=>handleAccountCounter(e,item)}/></td>
<td><input type="text" value={item.accountOwner}
name="accountName" onChange={(e)=>handleAccountCounter(e,item)}/></td>
<td><span onClick={()=>deleteAccount(item.id)}>X</span></td>
</tr>
)
})}
here is my handleAccountCounter
const handleAccountCounter=(event,counter)=>{
const index = accountCounter.indexOf(counter);
accountCounter[index][event.target.name]=event.target.value;
setAccountCounter(accountCounter)
}
But the state is not getting modified when in input field value={item.account}.dont know why..will you help me out
Upvotes: 2
Views: 66
Reputation: 1908
Use the previous state values to create a new array:
const App = () => {
const [accountCounter, setAccountCounter] = useState([
{ id: 1, account: "", accountOwner: "" },
{ id: 2, account: "hi", accountOwner: "" },
{ id: 3, account: "bu", accountOwner: "" }
]);
const handleAccountCounter = (event, counter) => {
setAccountCounter((prevAccountCounter) => {
const newCounter = [...prevAccountCounter];
newCounter[prevAccountCounter.indexOf(counter)][event.target.name] =
event.target.value;
return newCounter;
});
};
const deleteAccount = (id) => {
setAccountCounter((prevAccountCount) =>
prevAccountCount.filter((item) => item.id !== id)
);
};
return accountCounter.map((item, index) => (
<tr key={index}>
<td>
<input
type="text"
value={item.account}
name="account"
onChange={(e) => handleAccountCounter(e, item)}
/>
</td>
<td>
<input
type="text"
value={item.accountOwner}
name="accountOwner"
onChange={(e) => handleAccountCounter(e, item)}
/>
</td>
<td>
<span onClick={() => deleteAccount(item.id)}>X</span>
</td>
</tr>
));
};
Upvotes: 1
Reputation: 41
Using Kartikey's answer, but you should use a callback because state updates are asynchronous:
const handleAccountCounter = (event, counter) => {
setAccountCounter((prev) => {
let newCounter = [...prev];
newCounter[prev.indexOf(counter)][event.target.name] = event.target.value;
return newCounter;
});
};
This ensures that the state updates in the correct order. See here for more info: https://dmitripavlutin.com/how-react-updates-state/
Upvotes: 1
Reputation: 5002
Instead of this
const handleAccountCounter = (event,counter) => {
const index = accountCounter.indexOf(counter);
accountCounter[index][event.target.name]=event.target.value;
setAccountCounter(accountCounter)
}
Do like this
const handleAccountCounter = (event, counter) => {
let temp = [...accountCounter] // Make a copy of state and then perform operations
const index = temp.indexOf(counter);
temp[index][event.target.name] = event.target.value;
setAccountCounter(temp)
}
Upvotes: 1