Dynamically Create Toggle Switch List for Attendance w/ Hooks & MaterialUI
Tags: react, hooks, typescript, javascript
Published: 2020-12-24 07:37:16

## Who This Is For 
*You are creating a list with true/false options, such as an attendance list.
*You are trying to use `useState` with an `object` and/or `array` and it won’t work. 
*You want a codesand box with clear explanations of how & why.   

*Note  - This is Typescript. If you are new to Typescript, know this bit of code:  `: boolean`  or `: string` after a variable declaration indicates the data type to check for. Otherwise, the implementation is the same.*


## Sandbox 
{% codesandbox qiymy module=/src/components/Attending.tsx %} 

## Step 1 - Setup Initial Form Structure
Once you have the bones of your form ready, the first key to dynamically creating toggle switches is the code below:
```javascript
<FormGroup>
        {attendees.map((member, i) => {
            return (    
              <ListMembers             // ListMembers component creates the toggle switches
              key={i}                        // the ID React uess to track unique components and state changes
              member={member}    // an unique index from attendees array, containing a member object
              memberIdx={i}           // the array index number, needed for handleChange
              handleAttendingChange={handleAttendingChange}   
              />
            )
          })}
      </FormGroup> 
```
`<FormGroup>` is a MaterialUI group that nests the MaterialUI `<Switch>` component.  Between the `<FormGroup>` is a `map()` of the data (from state) to create the attendance list, in this case using `attendees`.

Please review the code comments to understand why each prop is listed. 

## Step 2 - Setup the Toggle Component
A simple component. The important aspect is the arguments passed to the `onChange` callback.

```javascript
onChange={() =>{ handleAttendingChange(memberIdx, !member.isAttending)}}  

```
The `!` lets the state flip-flop, otherwise `state` does not change. Only the array index of the member (`memberIdx`) is passback; we have access to the member object in the parent component so we only need a reference passed. 

## Step 3 - Handle The Change Function
Most toggle tutorials statically set a toggle value (see Resources below for useful articles on this method). 

However, we need a dynamic method as we are working with an array of objects. As such, the `handleChange` `setState` is implemented differently. 

```javascript
const updatedAttendee = attendees[memberIdx]  // from the state 'attendees' array, get the correct object for updatedAttendee
    updatedAttendee.isAttending = attendanceState // update the boolean of the attendee to indicate going/true || not/false

    const newAttendees = [...attendees]           // make a copy of previous state of attendees
    newAttendees[memberIdx] = updatedAttendee     // insert/overwrite array object of the attendee in question with the new version
    setAttendees(newAttendees)                    // update state  
```

 Unlike `SetState` in a React class, **`useState` overwrites the previous state, rather than mutating it AND in order for React to know of a state change, ‘useState’ needs a new object.** The 5 lines of code above creates the new object. 

To understand the details on `useState` for `arrays` and `objects`, check out:
*[A Guide to To UseState](https://blog.logrocket.com/a-guide-to-usestate-in-react-ecb9952e406c/#reacthooksupdatestate)
 and these two videos: 
*[React Hooks Tutorial - 4 - useState with object ]  (https://www.youtube.com/watch?v=-3lL8oyev9w)
*[React Hooks Tutorial - 5 - useState with array ](https://www.youtube.com/watch?v=RZ5wKYbOM_I) 
 

## Step 5 - Submit The Form
For the demo, fairy tale creatures who can attend are filtered into a separate list and considered submitted. 

How you `POST/PATCH` to your backend is unique and not covered here. 

#### Aside - Why Not Use Event.Target?
“`Event.target.value` is only useful for form elements with changing values.” - Andre
“If you had an input [textbox] with an `onChange` handler, then you'd want the `event.target.value`.” -Andre

A toggle property’s name is `checked` but all we need is the value (true/false) and pass back this value via a prop, `member.isAttending` in this demo. 


## Feedback?
Have thoughts or advice on the above implementation?

If so, drop a note. I'd love to hear and see your examples, explanations, and other details to clarify how/why/when.

## Resources
[A Guide to To UseState](https://blog.logrocket.com/a-guide-to-usestate-in-react-ecb9952e406c/#reacthooksupdatestate)
[React Hooks Tutorial - 4 - useState with object ]  (https://www.youtube.com/watch?v=-3lL8oyev9w)
[React Hooks Tutorial - 5 - useState with array ](https://www.youtube.com/watch?v=RZ5wKYbOM_I) 
[Static Toggle - Create a Toggle Switch in React as a Reusable Component]                       (https://www.sitepoint.com/react-toggle-switch-reusable-component/)
[StackOverFlow Conversation on Submitting a Form](https://stackoverflow.com/questions/59364171/react-hooks-grab-value-of-checkbox-onchange-and-pass-to-submitform)
[MaterialUI Switch - Official Documentation](https://material-ui.com/components/switches/)

## Special Thanks
Thanks to my dear friend Andre for walking me through the issues I had with the `handleChange` and which props to pass.