0

I have a checkbox for filters of products. What I want is to change the value of checked when click from false to true or vice-versa. I have defined a handleChangeChecked function to perform this operation which takes two arguments.

 const [Filters, setFilters] = useState([
        {
            id: 'brand',
            name: 'Brands',
            options: [
                { value: 'Casio', label: 'Casio', checked: false },
                { value: 'Yamaha', label: 'Yamaha', checked: false },
            ],
        },
        {
            id: 'size',
            name: 'No of Keys',
            options: [
                { value: 32, label: '32 Keys', checked: false },
                { value: 37, label: '37 Keys', checked: false },
                { value: 44, label: '44 Keys', checked: false },
                { value: 49, label: '49 Keys', checked: false },
                { value: 61, label: '61 Keys', checked: false },
                { value: 76, label: '76 Keys', checked: false },
            ],
        }

    ]


const handleChangeChecked = (section, value) => {
    console.log(section,value)      //brand Casio  (if I click on Casio Checkbox)
}

How can I achieve this functionality?

pilchard
  • 12,414
  • 5
  • 11
  • 23
Big Loot
  • 49
  • 4
  • Does this answer your question? [Updating deeply nested state with useState not working properly](https://stackoverflow.com/questions/69270887/updating-deeply-nested-state-with-usestate-not-working-properly) – pilchard Jul 23 '22 at 12:58
  • also: [React hooks: How do I update state on a nested object with useState()?](https://stackoverflow.com/questions/56802815/react-hooks-how-do-i-update-state-on-a-nested-object-with-usestate) and [React: Setting State for Deeply Nested Objects w/ Hooks](https://stackoverflow.com/questions/57798841/react-setting-state-for-deeply-nested-objects-w-hooks) – pilchard Jul 23 '22 at 12:58

1 Answers1

0

You have some other issues here in that the static data which does not change really shouldn't be in React state. Updating deep state is perfectly doable but also unnecessarily complex in this use case (unless there's more to it I don't know about).

However, maybe it comes from the server or something and that's why your example code does what it does -- so I'm going to ignore that for now in case.

To update deep like this I'd highly recommend using Immer. Its quite dirty without it because in React you have to do it by creating new state from the old one without mutating the original (which is a big React no-no). Immer takes that complexity away for you.

I'm also assuming the variable section is the same as the ID of each filter.

import produce from "immer"

// ... rest of code

const handleChangeChecked = (section, value) => {
    setFilters( produce((draft) => {
        const sectionToChange = draft.find((filter) => filter.id === section)
        const option = sectionToChange.options.find(option => option.value === value)
        option.checked = !option.checked
      }))
}

adsy
  • 8,531
  • 2
  • 20
  • 31
  • Hii Adam, I really like the way of using Immer but there is an error that occurred. ypeError: Cannot read properties of undefined (reading 'options'). Because the section argument is not used inside the function because it is greyed out but the value argument is not greyed out. – Big Loot Jul 23 '22 at 15:41
  • Oops sorry i made an error (conflicting variable names). Ive just edited it to fix. – adsy Jul 23 '22 at 15:51
  • heheh.. ya I already figured it out after few minutes of comment. Thanks. One more query, should I use onClick or onChange on input emelent. – Big Loot Jul 23 '22 at 15:53
  • Semantically, onChange is more correct. It barely matters on tickboxes on most platforms, but you can get weird stuff happening on mobile with onCLick – adsy Jul 23 '22 at 15:55