skip to Main Content

I need to create this kind of object when check the checkboxes

{
"targets": [
    {
      "kind": "foo",
      "channelId": "-897",
      "quote": "true",
      "gatewayName": "bbb"
    },{
      "kind": "bar",
      "channelId": "-1123",
      "quote": "true",
      "gatewayName": "aaa"
     }
   ]
}

and I have this snippet for my from

{gateways ? gateways.map((g) => {

            return (
              <Tooltip
                key={g.name}
                content={`${g.name} - ${g.kind}`}
              >

                <Switch
                  key={g.name}
                  id={g.name}
                  label={g.name}
                  name={g.name}
                  value={`{"kind":"${g.kind}","channelId":"${g.channelId}","gatewayName":"${g.name}","quote":"true"}`}
                  labelProps={{
                    className: "text-sm font-normal text-blue-gray-500",
                  }}
                  onChange={handleCheckboxChange}
                />
              </Tooltip>
            )

}) : "Loading..."}

I create the state

  const [checkboxes, setCheckboxes] = useState([]);

I’m trying to create the handleCheckboxChange

 const handleCheckboxChange = (e) => {
    const { name, checked, value } = e.target;

  
    if(checked){
      setCheckboxes(prev => ({ 
        targets: [prev.targets,JSON.parse(value)]
      }))
    }else{
      setCheckboxes(prev => ({ 
        targets: prev.filter(target => target !== JSON.parse(value))
      }))
    }

    console.log(checkboxes)
  };

But when I check the first checkbox I have two element in array, the first is undefined.
when I uncheck I get this error

TypeError: prev.filter is not a function

2

Answers


  1. The state for the checkboxes is being initialized as an empty array, however when handling the checkbox change with the function handleCheckboxChange() you’re setting the state to be an object. So the next time checked is changed, filter will not be available.

    if(checked) {
      setCheckboxes(prev => ({ // Returning an OBJECT
        targets: [prev.targets,JSON.parse(value)] 
      }))
    }
    
    else { 
                               // also returns an object
      setCheckboxes(prev => ({ // Filter will not be available due to "prev" being an object
        targets: prev.filter(target => target !== JSON.parse(value))
      }))
    }
    

    Also instead of doing this:

    value={`{"kind":"${g.kind}","channelId":"${g.channelId}","gatewayName":"${g.name}","quote":"true"}`}
    

    You could use object destructuring:

    value={ { ...g } }
    
    Login or Signup to reply.
  2. If the input is checked you are returning this to your state :

    { targets: [prev.targets, JSON.parse(value)] }
    

    This is an object so the state is no longer and array that’s why you got

    TypeError: prev.filter is not a function

    When you try to uncheck

    However, since your state is initialized as [] the first check action will not find prev.targets so thats why it is undefined

    If I understood well, you want to store an array of objects, so why you want your state to be an object with only one preoperty targets that hold an array ? you can simply make it an array and you know it is representing targets :

    if (checked) {
      setCheckboxes((prev) => [...prev, JSON.parse(value)]);
    } else {
      setCheckboxes((prev) =>
        prev.filter((target) => JSON.stringify(target) !== JSON.stringify(JSON.parse(value)))
      );
    }
    

    Note: you have to use JSON.stringify to compare two objects, otherwise the result is always false.


    But if you insist, what you have to do is to initilize your state this way :

    const [checkboxes, setCheckboxes] = useState({ targets: [] }); // make the property targets exist by default
    

    and your code is fine you only have to change this line :

    targets: prev.filter(target => target !== JSON.parse(value)) // prev is an object while prev.target is what you need
    

    with

    targets: prev.targets.filter((target) => JSON.stringify(target) !== JSON.stringify(JSON.parse(value)))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search