0

I have created a functional component and state hook. I want to push all the checked items into a particular array of e.target.name of the useState hook.

  const [formInput, setFormInput] = useState({
    areaOfInterest: []
  });

This handle I got help from an stackoverflow post: I want to store the checkbox datas into functional state hook but unable to do

  const handleCheck = ({ target }) => {
    const { name: blockName, checked, value } = target; 
    //console.log(value);
    if (checked) {
      formInputt[blockName].push(value); 
    } else {
      const index = formInputt[blockName].indexOf(value);
      formInputt[blockName].splice(index, 1);
    }

    setFormInputt(formInputt); 
  };

  <Form.Group>
    <Form.Label>Area of Interest</Form.Label>
    <Form.Check
      name="areaOfInterest"
      label="Dedicated Teams"
      onChange={handleCheck}
      value="Dedicated Teams"
    />
    <Form.Check
      name="areaOfInterest"
      label="Cloud Expert Advice & Support"
      onChange={handleCheck}
      value="Cloud Expert Advice & Support"
    />
    <Form.Check
      name="areaOfInterest"
      label="Software Development"
      onChange={handleCheck}
      value="Software Development"
    />
    <Form.Check
      name="areaOfInterest"
      label="Digital Transformation"
      onChange={handleCheck}
      value="Digital Transformation"
    />
  </Form.Group>

Every time the user clicks on a checkbox, I want to add the value to an array and filter out what isn't there.

I am finding this very difficult and I think it should be quite simple. Can someone point me in the right direction? Is there a way to simply have a function trigger that reads the checked/unchecked status of my form input elements and then updates my state array accordingly?

Pratima Gautam
  • 317
  • 1
  • 6
  • 21

2 Answers2

2

Never mutate state. If you find yourself calling an updater like this setState(state), you've done something wrong.

Instead, create a new array or do a map/filter inside the updater. The best option might be to do it all inside the setter using a functional update.

const handleCheck = ({ target }) => {
  const { name: blockName, checked, value } = target;
  setFormInput((prevState) => {
    if (prevState[blockName]) {
      if (checked) {
        return { ...prevState, [blockName]: [...prevState[blockName], value] }
      } else {
        return {
          ...prevState,
          [blockName]: prevState[blockName].filter(option => option != value)
        }
      }
    } else { 
      if (checked) { 
        return {
          ...prevState,
          [blockName]: [value]
        }
      } else {
        return prevState
      }
    }
  })
}
Brian Thompson
  • 13,263
  • 4
  • 23
  • 43
1

You want a handle that pushes the selected checkboxes to the array areaOfInterest inside formInput right?

Edit:

const handleCheck = ({ target }) => {
    const { name: blockName, checked, value } = target;

    setFormInput(prevState => {
      if (checked) {
        return { 
          ...prevState, 
          [blockName]: [...prevState[blockName], value] 
        }
      } else {
        return {
          ...prevState,
          [blockName]: prevState[blockName].filter(element => element !== value)
        }
      }
    })
  }

Check the example: https://codesandbox.io/s/admiring-bohr-58wh4?fontsize=14&hidenavigation=1&theme=dark

rMonteiro
  • 1,371
  • 1
  • 14
  • 37
  • Your answer should contain the actual answer, not a link off-site. Also the actual answer itself mutates state which is against the rules of react – Brian Thompson Feb 10 '20 at 18:00
  • [React docs](https://reactjs.org/docs/react-component.html#state): "Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable." – Brian Thompson Feb 10 '20 at 18:04
  • 1
    @BrianThompson you are right, I updated the answer and posted the code – rMonteiro Feb 11 '20 at 10:42