brain storm
brain storm

Reputation: 31252

Toggle switch button not working in reactJs app

I want a container with table that has one column "enabled" which can be toggled. I want to save the state of toggle in object I used to display the row (In the example below, I want to store it in enable attribute of student object). I have table and toggle button displaying properly. But the toggle button is not clickable/togglable and doesnt store the state. live code here.

Here is my code

class student {
  constructor(id, name, age,email,enable) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.email = email;
    this.enable = enable;
  }
}


const Switch = ({ isOn, handleToggle}) => {
    return (
    <>
      <input
        checked={isOn}
        onChange={handleToggle}
        className="react-switch-checkbox"
        id={`react-switch-new`}
        type="checkbox"
      />
      <label
        className="react-switch-label"
        htmlFor={`react-switch-new`}
      >
        <span className={`react-switch-button`} />
      </label>
    </>
  );
};




class Table extends React.Component {
  constructor(props) {
      super(props)
      this.state = {
         students: [ new student(1, 'foo', 12, '[email protected]', true), 
                    new student(2, 'bar', 22, '[email protected]', false),
                    new student(3, 'foobar', 44, '[email protected]', true),
                    new student(4, 'foofoo',57,  '[email protected]', false)
                    ]
      }
   }



   renderTableHeader() {
      let header = Object.keys(this.state.students[0])
      return header.map((key, index) => {
         return <th key={index}>{key.toUpperCase()}</th>
      })
   }

   renderTableData() {
      return this.state.students.map((student, index) => {
         const { id, name, age, email, enable } = student //destructuring
         //const [value, setValue] = useState(false);
         return (
            <tr key={id}>
               <td>{id}</td>
               <td>{name}</td>
               <td>{age}</td>
               <td>{email}</td>
             <td><Switch
        isOn={enable}
        handleToggle={() => student.enable=!enable}
      /></td>
            </tr>
         )
      })
   }

   render() {
      return (
         <div>
            <h1 id='title'>React Dynamic Table</h1>
            <table id='students'>
               <tbody>
                  <tr>{this.renderTableHeader()}</tr>
                  {this.renderTableData()}
               </tbody>
            </table>
         </div>
      )
   }
}

ReactDOM.render(<Table />, document.getElementById('root'));  

Here is the screenshot of how page looks enter image description here

Upvotes: 1

Views: 5271

Answers (1)

ravibagul91
ravibagul91

Reputation: 20755

The issue is, you cannot directly change the state like,

handleToggle={() => student.enable=!enable}

This will never change your state. To change your state you must use setState.

You should have a dedicated function to toggle your state,

handleToggle = (id) => {
   this.setState({
      students: this.state.students.map(std => {
        if(parseInt(std.id) === parseInt(id)){  //parse id to integer for safer side
          return {...std, enable: !std.enable}
        }else{
          return std;
        }
      })
   })
}

You should provide this function to your Switch. Also provide id for updation.

<Switch
    isOn={enable}
    id={id}   //provide id for updation
    handleToggle={this.handleToggle}   //provide function reference
/>

You need to make some changes to your Switch,

const Switch = ({ isOn, handleToggle, id}) => {   //take prop id
  return (
    <>
      <input
        checked={isOn}
        onChange={() => handleToggle(id)}   //call handleToggle using id
        className="react-switch-checkbox"
        id={`react-switch-new${id}`}        // Make it unique by adding id
        type="checkbox"
      />
      <label
        className="react-switch-label"
        htmlFor={`react-switch-new${id}`}   // Make it unique by adding id
      >
        <span className={`react-switch-button`} />
      </label>
    </>
  );
};

Demo

Upvotes: 3

Related Questions