iam new in react. I would like create a submit form in modal. But i got some issue.
In my form there is textbox and multiple checkbox (array object), if i give an event in this checkbox it will add new key (IsChecked = true). The problem is come when i tried to submit the form by click button, the first click it's not working (the new param on useState not updated), but when i click for the twice it works (useState updated the new param).
Here's my code:
import React, {useState,useEffect} from 'react'
export default function Form() {
const listNav = [{ID:'1',Name:'Dashboard'},{ID:'2',Name:'Profile'}];
const [NIP,setNIP] = useState("");
const [NavArray,setNav] = useState(listNav);
const [messagePost, setMsgPost] = useState("");
const [error, setMsgError] = useState("");
const handleNavParent = (id,e) =>{
let ischecked = e.target.checked;
if(ischecked){
const checkBoxArray = NavArray;
const index = checkBoxArray.findIndex(object => object.ID === id);
checkBoxArray[index].IsChecked = !checkBoxArray[index].IsChecked;
setNav(checkBoxArray);
}
}
const submitHandler = e => {
e.preventDefault();
if(NIP && NavArray && countChk > 0){
let dataParam = {NIP:NIP, NavArray: NavArray};
console.log(dataParam);
setMsgError("");
}else{
setMsgError("Please fill up the form with correctly.");
}
}
return (
<form id="form-user-access" autoComplete="off" onSubmit={submitHandler}>
<input type="text" name="NIP" pattern="[0-9]*" onInput={(e)=>handleNumber(e)} value={NIP} className="form-control form-control-sm" />
{ listNav.map((v) => (
<div className="col-sm-6">
<div className="card card-custome gutter-b">
<div className="card-body p-2">
<p className="text-info">{v.TypeName} menu</p>
<label className="font-size-sm"><input type="checkbox" value={v.ID} id={v.ID} onChange={(e)=>{handleNavParent(v.ID,e)}} /> {v.Name}</label>
</div>
</div>
</div>
))}
<button className="btn btn-primary" type="submit">Save changes</button>
</form>
)
}
In submitHandler() function, when i submit the form (the condition i tick the Dasboard(checkbox)), the first click it show:
[NIP:123,NavArray:[{ID:'1',Name:'Dashboard'},{ID:'2',Name:'Profile'}]]
when i click it or submit again it show:
[NIP:123,NavArray:[{ID:'1',Name:'Dashboard',IsChecked:true},{ID:'2',Name:'Profile'}]]
What i would like to do is got the result like the second click, but only once click/submited. How can i fix my code?
You are mutating your state object in handleNavParent
.
const handleNavParent = (id, e) =>{
let ischecked = e.target.checked;
if (ischecked) {
const checkBoxArray = NavArray; // <-- state reference
const index = checkBoxArray.findIndex(object => object.ID === id);
checkBoxArray[index].IsChecked = !checkBoxArray[index].IsChecked; // <-- state mutation!
setNav(checkBoxArray); // <-- saved reference back into state
}
}
This doesn't trigger a rerender since the NavArray
array reference never updated to a new array reference. You don't see the updated state until you click to submit the form and the submitHandler
calls setMsgError
and updates state and triggers a rerender with the side-effect from above.
Use a functional state update to toggle the checked value.
const handleNavParent = (id, e) =>{
const { checked } = e.target;
if (checked) {
setNav(state => state.map(el => el.ID === id ? {
...el,
IsChecked: !el.IsChecked,
} : el));
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.