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?

2
  • The handler you copied is not a good one. It mutates state. Commented Feb 10, 2020 at 17:45
  • @BrianThompson Can you give me any suggestions? Commented Feb 10, 2020 at 17:49

2 Answers 2

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
      }
    }
  })
}
Sign up to request clarification or add additional context in comments.

5 Comments

It creates an array out of an object, but I found some issues with that example so I removed it. Try the functional update, I have tested it.
When I click on the checkbox I got this error: TypeError: prevState[blockName] is not iterable
Is it not defaulted to an empty array like your example? I guess this assumes it is. I can update the answer to account for it if that's what is needed.
Yeah, array is empty by default.
I just updated it to check if the array exists first, if not it creates one.
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

3 Comments

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
React docs: "Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable."
@BrianThompson you are right, I updated the answer and posted the code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.