Reputation: 351
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 !
Upvotes: 1
Views: 1081
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>
);
Upvotes: 2