0

I have Switches created dynamically by a map like this: https://i.stack.imgur.com/jDLbS.png

By this code:

const [enabled, setEnabled] = useState(false)

return(
...
{people.map((person) => (
             ...
             <Switch
                    checked={enabled}
                    onChange={setEnabled}
                    className={classNames(
                        enabled  ? 'bg-indigo-600' : 'bg-gray-200',
                        'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500'
                    )}
           ...
           </Switch>
...
))

And it's works but when I click one Switcher all switchers change together. This is happening because all Switches are created with the same "reference" enabled. How I set an individual var to each Switcher without Hardcoding individuals [enabled, setEnabled] to each one (I have more than 450 lines using this Switch) and How can I call a function when onChange is called without messing with this setEnabled function?

SrMilton
  • 45
  • 6

2 Answers2

1

You need to create an object in your state instead of a boolean. and use id/index as a key of each item in object. try like this in below example I am using index as key.

const [enabled, setEnabled] = useState({})

const onEnable = (index, value) => {
  let _enabled = {...enabled};
  _enabled[index] = value
  setEnabled(_enabled)
}

return (

    {
      people.map((person, index) => ( 
              <Switch 
                 checked = {!!enabled[index]}
                 onChange = {(e)=> onEnable(index, e.target.checked)} 
                  // instead of index I recommend using id or any unique key present in your person array 
              </Switch>
            ))
    }

A working code sandbox example you can fine here

https://codesandbox.io/s/magical-grass-yx1qsg?file=/src/App.js

Abhi
  • 1,127
  • 1
  • 12
  • 25
  • For some reason my code is not recognizing "checked" from "e.target.checked" ```Cannot read properties of undefined (reading 'checked')```. Can you explain what is those "!!" on enabled[index]? – SrMilton Aug 23 '22 at 04:17
  • I needed to change the ```e.target.checked``` to just ```e``` and it's working perfectly. Thanks. – SrMilton Aug 23 '22 at 04:37
  • Btw how can I preset all to True? I have to loop through all index and set one by one? – SrMilton Aug 23 '22 at 04:40
  • instead of ```{}``` in your initial state you need to do create an object with all values true. Eg => ```{1: true, 2: true}.... ``` 1, 2 you can replace with your keys check codesandbox again. – Abhi Aug 23 '22 at 10:02
0

You can store an array of objects in your useState hook, allowing you to modify only the object that needs to be changed.

const [enabled, setEnabled] = useState([{_id: 123, enabled: False}])

To update the state:

const newData = { _id: 123, enabled: True }
setEnabled(data => [...data, newData])
Lucas Raza
  • 499
  • 1
  • 4
  • 13
  • What is this ```...state```? "value" and "enabled" is supposed to be the same thing? – SrMilton Aug 23 '22 at 04:32
  • I corrected it. `...data` de-structures the values stored in enabled. By passing in your the newData object, it will update the enabled array and either replace the old object stored that matches the '_id' property or store a new object. – Lucas Raza Aug 23 '22 at 14:46