简体   繁体   中英

Problem twice click on submit handler in React JS

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?

Issue

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.

Solution

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM