Search code examples
reactjsreact-hooksspread

how change value in spread useState?


I want to change the value of a checkbox and get its value.

with:

const[check, setCheck] = useState()

  const handleChange = () =>{
    setCheck(prevValue => !prevValue)
    console.log(check)
  }

it works fine, it shows true and false by clicking

with:


 const [checked, setChecked] = useState({
     checked1: false,
     chekced2: false, 
    ...
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setChecked((prevState) => {
      return {
        ...prevState,        
        [name]: value
      };
    });    
    console.log(checked.checked1)    
  };

it only shows false only, if it is checked or not. Where is my mistake?


Solution

  • This partly is because you are logging immediately after the set state. React does not immediately update the value, it's flushed later at the end of the call stack and becomes what you expect on the next re-render.

    More info: https://beta.reactjs.org/apis/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value

    What you need to do depends on if the <input> is controlled or not. It's controlled if you pass the checked prop to it and uncontrolled if you do not pass it.

    For controlled use:

    
      // You also need to ensure your default state has all the
      //names of each checkbox rendered from the beginning and they are 
      // set to false. THIS IS CRUCIAL IN THIS PATTERN! 
      // Or e.target.checked would be undefined.
      // e.g.
      //
      // const [checked, setChecked] = useState({
      //     name1: false,
      //     name2: false,
      //     name3: false,
      //     ... // etc
      // })
    
      const handleChange = (e) => {
        const { name, checked} = e.target;
        setChecked((prevState) => {
          return {
            ...prevState,        
            [name]: checked
          };
        });       
      };
    
     // Input must be bound like
     // <input name="your-name" onChange={handleChange} checked={this.state.checked["your-name"]} />
     
    

    For uncontrolled use:

      const handleClick = () => {
        const { name } = e.target;
        setChecked((prevState) => {
          return {
            ...prevState,        
            [name]: !Boolean(prevState[name])
          };
        });       
      };
    
     // Input must be bound like
     // <input name="your-name" onClick={handleChange} defaultChecked={false} />