skip to Main Content

As a React beginner exercice I have a component checkbox for a list of devices. If a device is checked, I want my App parent element to display the name of the device. I tried several ways to do it but cannot achieve it.
Here is my code

Checkbox.jsx

import { useState, useEffect } from "react"

const Checkbox = ({ label, name, sendData}) => {
  const [isChecked, setIsChecked] = useState(false);

  const handleChange =() => {
    setIsChecked({isChecked: !isChecked} )
  }
  
  useEffect(()=> {
      sendData(isChecked)
  })

  return (
    <div className="checkbox-wrapper">
      <label>
        <input
          type="checkbox"
          checked={isChecked }
          onChange={handleChange}
          name={name}
        />
        <span>{label}</span>
      </label>
    </div>
  );
};

export default Checkbox;

App.js

import { useState } from 'react';
import Checkbox from './components/Checkbox';
import './App.css';
import { useState } from 'react';
import Checkbox from './components/Checkbox';
import './App.css';

function App() {

  const [ownDevice, setOwnDevice] = useState(false)

  const sendData = (childData) => {
    setOwnDevice(childData)
  }

  const displayDevice = (Checkbox) => {
     if (ownDevice) {
       return Checkbox.name
     }
  }

return(
  <div className="App">
    <h1>What devices do you own?</h1>
    <Checkbox label="laptop" name="laptop" sendData={sendData} />
    <Checkbox label="desktop" name="desktop" />
    <Checkbox label="phone" name="phone" />
    <p>{displayDevice}</p>
  </div>

)


}

export default App;

2

Answers


  1. I have solved your problem this way, hope it helps:

    function App() {
      const [ownDevice, setOwnDevice] = useState(false)
      const [displayName, setDisplayname] = useState('')
      const sendData = (childData) => {
        setOwnDevice(childData)
      }
      return (
        <div className="App">
        <h1>What devices do you own?</h1>
        <Checkbox label="laptop" name="laptop" sendData={sendData}
        setOwnDevice={setOwnDevice}
        />
        <Checkbox label="desktop" name="desktop" sendData={sendData}
        setOwnDevice={setOwnDevice}
        />
        <Checkbox label="phone" name="phone"  sendData={sendData}
        setOwnDevice={setOwnDevice}
        />
        <p>{ownDevice}</p>
      </div>
      );
    }
    

    CheckBox file :

    const Checkbox = ({ label, name, sendData,setOwnDevice}) => {
      const [isChecked, setIsChecked] = useState(false);
    
      const handleChange =(e) => {
        setIsChecked(true)
        const { name, value } = e.target;
        setOwnDevice(name)
      }
      
    
      return (
        <div className="checkbox-wrapper">
          <label>
            <input
              type="checkbox"
              checked={isChecked }
              onChange={handleChange}
              name={name}
            />
            <span>{label}</span>
          </label>
        </div>
      );
    };
    
    Login or Signup to reply.
  2. First of all, the code you have written will be stuck in an infinite render loop if we update the parent state on changing the isChecked state because you haven’t provided a dependency to useEffect which means it will update the parent state every time your component renders.

    You need to remove the useEffect altogether. And secondly you can simple pass the setOwnDevice method directly to the child. The child will update the parent state which will result in a rerender. We can then use that state to display the selected device. The updated Checkbox.jsx component will look like this:

    import { useState, useEffect } from "react"
    
    const Checkbox = ({ label, name,  setOwnDevice}) => {
      const [isChecked, setIsChecked] = useState(false);
    
      const handleChange =() => {
        setIsChecked(!isChecked)  
        setOwnDevice(name)
      }
    
      return (
        <div className="checkbox-wrapper">
          <label>
            <input
              type="checkbox"
              checked={isChecked}
              onChange={handleChange}
              name={name}
            />
            <span>{label}</span>
          </label>
        </div>
      );
    };
    
    export default Checkbox;
    

    Then update the App.js file:

    import React, { useState } from 'react';
    import Checkbox from './components/Checkbox';
    import './App.css';
    
    function App() {
    
      const [ownDevice, setOwnDevice] = useState("")
    
    return(
      <div className="App">
        <h1>What devices do you own?</h1>
        <Checkbox label="laptop" name="laptop" setOwnDevice={setOwnDevice} />
        <Checkbox label="desktop" name="desktop" setOwnDevice={setOwnDevice} />
        <Checkbox label="phone" name="phone" setOwnDevice={setOwnDevice} />
        <p>{ownDevice}</p>
      </div>
    
    )
    
    
    }
    
    export default App;
    

    This could still be improved further because currently it won’t show two checked devices at the same time.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search