Student
Student

Reputation: 351

Checkboxes are not working properly in React js

I am assigned a simple task to render permissions of different users using React JS. There is a little problem and I think the page is not rendered according to the received props data. Here is my code with little bit explanation.

// my App.js file
import { useState } from "react";
import "./App.css";
import Dropdown from "./components/Dropdown";
import Permissions from "./components/Permissions";

function App() {
  const users = [
    {
      id: 1,
      name: "Cirilla",
      permissions: ["Post"],
    },
    {
      id: 2,
      name: "Michael Scofield",
      permissions: ["Post", "Fetch", "Write"],
    },
    {
      id: 3,
      name: "Thomas Shellby",
      permissions: [],
    },
    {
      id: 4,
      name: "Jon Snow",
      permissions: ["Fetch", "Post"],
    },
  ];
  let [currentUser, setCurrentUser] = useState(users[0]);
  const permissions = [
    {
      id: 1,
      name: "Post",
      val: currentUser.permissions.includes("Post"),
    },
    {
      id: 2,
      name: "Fetch",
      val: currentUser.permissions.includes("Fetch"),
    },
    {
      id: 3,
      name: "Write",
      val: currentUser.permissions.includes("Write"),
    },
    {
      id: 4,
      name: "Read",
      val: currentUser.permissions.includes("Read"),
    },
  ];

  const dropDownChangeHandler = (value) => {
/*this function is executed whenever the dropdown is value is changed. setCurrentUser causes the app function to run again and the array permissions is created again according to the selected user*/
    const user = users.find((item) => item.name === value);
    setCurrentUser(user);
  };

  console.log(currentUser);

  return (
    <div className="container">
      <Dropdown list={users} onChange={dropDownChangeHandler} />
      <Permissions list={permissions} />
    </div>
  );
}

export default App;

Here is the permissions.js file

import PermissionsItem from "./PermissionsItem";

const Permissions = (props) => {
  return (
    <div>
      {props.list.map((item) => (
        <PermissionsItem key={item.id} item={item} />
      ))}
    </div>
  );
};

export default Permissions;

And finally, here is the permissionItem.js file

import React, { useEffect, useState } from "react";

const PermissionsItem = (props) => {
  /* const [checkboxValue, setCheckBoxValue] = useState(props.item.val); // here useState does not provide the correct value so I have to use useEffect for this */

   useEffect(() => {
     setCheckBoxValue(props.item.val);
   }, [props.item.val]);

  const checkBoxChangeHandler = (event) => {
    setCheckBoxValue(event.target.checked);
  };

  return (
    <div className="permission-item">
      <label htmlFor={props.item.id} className="perm-li">
        {props.item.name}
      </label>
      <input
        id={props.item.id}
        type="checkbox"
        checked={checkboxValue}
        onChange={checkBoxChangeHandler}
      />
    </div>
  );
};

export default PermissionsItem;

The problem is that when I check any checkbox value of any user (suppose Cirilla), and then select the other user from dropdown (suppose Michael Scofield), the checked permission of first user, Cirilla, is also checked in Michael Scofield's permission. The Micheal's data is displayed correctly in the console but checkboxes are not rendered accordingly.

Please Help I have already wasted my whole week on this :( Any kind of help or suggestion is much appreciated. Thank you in advance !

Here is the image

Upvotes: 1

Views: 1081

Answers (1)

Okan Karadag
Okan Karadag

Reputation: 3045

The problem is that your do check by user in permission. There is no dependecy between the "permission" component and currentUser, so it does not render.

App:

const users = [
    {
      id: 1,
      name: "Cirilla",
      permissions: ["Post"],
    },
    {
      id: 2,
      name: "Michael Scofield",
      permissions: ["Post", "Fetch", "Write"],
    }
    ///...
 
  ];
  const permissions = [
    {
      id: 1,
      name: "Post"
    },
    {
      id: 2,
      name: "Fetch"
    }
    ///...
  ];
const dropdownChange = (e) => {
    setCurrentUser(users.find(x => x.id == e.target.value))
}
return (
    <div className="App">
      <div className="container">
     <select  value={currentUser?.id} onChange={dropdownChange} >
       {users.map((item) => {
          return <option value={item.id}>{item.name}</option>})
       }
     </select>
      <Permissions list={permissions} currentUser={currentUser}/>
    </div>
    </div>
  );

Permission and PermissionItem

const Permissions = (props) => {
  return (
    <div>
      {props.list.map((item) => (
        <PermissionsItem 
        key={item.id} 
        item={item}
        hasItem={props.currentUser.permissions?.includes(item.name)}/>
      ))}
    </div>
  );
};
const PermissionsItem = (props) => {
  const [checkboxValue, setCheckBoxValue] = useState(false); 

useEffect(() => {
  setCheckBoxValue(props.hasItem)
},[props.hasItem])
  const checkBoxChangeHandler = (event) => {
    //TODO users update
    setCheckBoxValue(event.target.checked);
  };

  return (
    <div className="permission-item">
      <label htmlFor={props.item.id} className="perm-li">
        {props.item.name}
      </label>
      <input
        id={props.item.id}
        type="checkbox"
        checked={checkboxValue}
        onChange={checkBoxChangeHandler}
      />
    </div>
  );

Edit friendly-lalande-4zkbvv

Upvotes: 2

Related Questions