unicorn_surprise
unicorn_surprise

Reputation: 1109

Undefined e.target.name for toggled state component

I'm running into errors when trying to set up a list of toggle/switches using useState. All of the initial states work properly and the page renders, however when I click on any toggle I get the following error: TypeError: Cannot read property 'name' of undefined. I just need to set the state of the one I clicked on. Thanks for any help in advance.

import React, {useState} from 'react'
import Dashboard from './Dashboard'
import Switch from "react-switch"
import styles from './Settings.module.scss'

const Settings = () => {

const [privacyToggles, setprivacyToggles] = useState({
    newContentNotification: false,
    newCommentSubscribed: true,
    newCommentCommented: true,
    publicDonationInfo: false
})

const handleToggleChange = (e) => {

     setprivacyToggles({
         ...privacyToggles,
         [e.target.name]: !privacyToggles[e.target.name]
     })
}

return (
    <>  
        <Dashboard />
        <div className="section">
            <div className="container">
            <h2 className="title is-4">Settings</h2>
                <h3 className="title is-5">Privacy Settings</h3>
                <div className="columns">
                    <div className={styles.toggleList + " column is-full"}>
                        <label className={styles.toggleLabel}>
                            <Switch 
                                onChange={handleToggleChange} 
                                checked={privacyToggles.newContentNotification}
                                name="newContentNotification"
                            />
                            <span className={styles.toggleText}>Receive notification of new content published on the website</span>
                        </label>
                        <label className={styles.toggleLabel}>
                            <Switch 
                                onChange={handleToggleChange} 
                                checked={privacyToggles.newCommentSubscribed}
                                name="newCommentSubscribed"

                            />
                            <span className={styles.toggleText}>Receive notification when somebody adds a comment to an article I am subscribed to</span>
                        </label>
                        <label className={styles.toggleLabel}>
                            <Switch 
                                onChange={handleToggleChange} 
                                checked={privacyToggles.newCommentCommented}
                                name="newCommentCommented"

                            />
                            <span className={styles.toggleText}>Receive notification when somebody adds a comment to an article I commented on</span>
                        </label>
                        <label className={styles.toggleLabel}>
                            <Switch 
                                onChange={handleToggleChange} 
                                checked={privacyToggles.publicDonationInfo}
                                name="publicDonationInfo"
                            />
                            <span className={styles.toggleText}>Publish information about my donations and make them public on my profile</span>
                        </label>
                    </div>
                </div>
            </div>
        </div>
    </>
)
}

export default Settings

Upvotes: 0

Views: 210

Answers (2)

Drew Reese
Drew Reese

Reputation: 203587

Switch onChange returns the new checked value of the switch, the event, and the id prop.

API

onChange ([checked], [event], [id]) Invoked when the user clicks or drags the switch. It is passed three arguments: checked, which is a boolean that describes the presumed future state of the checked prop (1), the event object (2) and the id prop (3).

If you change your handleToggleChange to receive the value and id parameters then you can correlate the field with the changed value.

const handleToggleChange = (value, e, id) => {
  setprivacyToggles({
    ...privacyToggles,
    [id]: value
  });
};

Then pass the "name" on the id prop when attaching the onClick handler

<Switch
  onChange={handleToggleChange}
  checked={privacyToggles.newContentNotification}
  id="newContentNotification"
/>

Edit react-switch state

Upvotes: 1

Kid
Kid

Reputation: 1240

NEW Okay, I've edited the answer.

const handleToggleChange = (...args) => {
    setprivacyToggles({
      ...privacyToggles,
      [args[2]]: args[0]
    });
  };

WRONG react-switch is designed to get the opposite value through onChange event.

You can check here.

You should build your own toggle component in order to get your desired result.

Upvotes: 1

Related Questions