set switch toggles checked value from states

Viewed 44

I am getting a list object from api which looks like allSettings list. i want to set the state of each item on that list so I can use it to define the checked status of toggle and can change state when there is change on toggle.

const Settings = () => {

    allSettings= [{name:"Setting1", value= true}, {name:"Setting2", value= true}, 
    {name:"Setting3", value= true},{name:"Setting4", value= false},{name:"Setting5", value= true}, 
     {name:"Setting6", value= true},{name:"Setting7", value= true}]
    
const[settings, setSettings]= useState({

       // i want to set the state of all allsettings's item in here
    });

    function handleChange(evt) {
       //to change state of toggle
    }
    return ( 
        <div>
            {
               allsettings.map(item => {
                    return (
                        <div>
                            <Switch
                                checked= {item.value}  //for now i am using item value
                                color="primary"
                                name={item.name}
                                inputProps={{ "aria-label": "primary checkbox" }}
                                onChange=   {handleChange}                         
                            />
                            <label>
                                {item.name}
                            </label>
                           </div>                    
                    );
                })
            }
   
        </div>


     );
}
 
export default Settings;
3 Answers

Update state like below,

function handleChange(id) {
    setSettings((prev) => {
      const idx = prev.findIndex((v) => v.id === id);
      prev[idx] = { ...prev[idx], value: !prev[idx].value }; //toggle logic
      return [...prev];
    });
  }

Completed code

import { Switch } from "@material-ui/core";
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Settings />
    </div>
  );
}

const Settings = () => {
  const allSettings = [
    { id: 1, name: "Setting1", value: true },
    { id: 2, name: "Setting2", value: true },
    { id: 3, name: "Setting3", value: true },
    { id: 4, name: "Setting4", value: false },
    { id: 5, name: "Setting5", value: true },
    { id: 6, name: "Setting6", value: true },
    { id: 7, name: "Setting7", value: true }
  ];

  const [settings, setSettings] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchData().then((result) => {
      setSettings(result);
      setLoading(false);
    });
  }, []);

  const fetchData = () => {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(allSettings);
      }, 2000);
    });
  };

  function handleChange(id) {
    setSettings((prev) => {
      const idx = prev.findIndex((v) => v.id === id);
      prev[idx] = { ...prev[idx], value: !prev[idx].value };
      return [...prev];
    });
  }
  return (
    <div>
      {(!loading &&
        settings.map((item) => {
          return (
            <div>
              <Switch
                checked={item.value} //for now i am using item value
                color="primary"
                name={item.name}
                inputProps={{ "aria-label": "primary checkbox" }}
                onChange={() => handleChange(item.id)}
              />
              <label>{item.name}</label>
            </div>
          );
        })) || <>Loading....</>}
    </div>
  );
};

codesandbox - https://codesandbox.io/s/wonderful-feynman-es6x0?file=/src/App.js

You need to declare the states then define them like so

class YOURNAME extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      stateOne: ""
    };
  }
  yourFunction(){
    this.setState({
      stateOne: "My State"
    });
  }

The simple method I often use:

const Settings = () => {
  const [settings, setSettings] = useState({});

  // Get data from a api, so may you need use the Effect Hook
  useEffect(() => {
    // The origin object array
    // Well, you can get it from a api
    const allSettings = [
      { name: "Setting1", value: true },
      { name: "Setting2", value: true },
      { name: "Setting3", value: true },
      { name: "Setting4", value: false },
      { name: "Setting5", value: true },
      { name: "Setting6", value: true },
      { name: "Setting7", value: true }
    ];

    // Convert the origin array to an object
    // Like:
    // { "Setting1": true, "Setting2": false, ... }
    const allSettingsMap = allSettings.reduce((resMap, current) => {
      return { ...resMap, [current.name]: current.value };
    }, {});

    setSettings(allSettingsMap);
  }, []);

  // now you can handle items' change simply
  function handleChange(e) {
    const name = e.target.name;
    setSettings({ ...settings, [name]: !settings[name] });
  }

  return (
    <div>
      {/* map the keys is just one method */}
      {Object.keys(settings).map((name) => {
        return (
          // tip: give a key
          <div key={name}>
            <Switch
              checked={settings[name]} //for now i am using item value
              color="primary"
              name={name}
              inputProps={{ "aria-label": "primary checkbox" }}
              onChange={handleChange}
            />
            <label>{name}</label>
          </div>
        );
      })}
    </div>
  );
};
Related