在localStorage中,我有一个对象数组(项目),每个对象都有一些属性,包括它自己的数组(项目)。我想将一系列项目显示为Material-ui表,效果很好。我也可以从中添加和删除项目。但是,在编辑该数组中的值时遇到了一个问题。我得到的最接近的解决方案要求我两次键入每个符号,然后浏览器失去对输入字段的关注,因此我不得不再次单击它。您可以在此处查看该项目:
You can see the project here
有问题的组件是ProjectDetails
和ProjectEmployeesTable
,但是我不知道问题出在哪里,因为我遇到了ProjectEmployeesTable
不能正确重新渲染的问题。
要查看模拟中的组件,您必须选择项目,添加一个新项目,将其保存,然后打开编辑菜单,然后尝试添加新员工并编辑其ID。
ProjectEmployeesTable:
export default function ProjectEmployeesTable(props)
{
const [employees,setEmployees] = useState([]);
//refresher is my fix for the component not re-rendering after updating employees
const [refresher,setrefresher] = useState(true);
const [selectedId,setSelectedId] = useState(0);
var idd=0;
useEffect( () => {
if(props.employees.length!=0){
setEmployees(props.employees);
setrefresher(!refresher)
}
},[props.employees])
function findEmployee(employee) {
return employee.employeeID === idd;
}
function handleIdChange(id,event) {
idd=id;
var tableEmployees = employees;
const employeeIndex=employees.findIndex(findEmployee);
console.log(idd,id,employeeIndex);
tableEmployees[employeeIndex].employeeID=event.target.value;
setEmployees(tableEmployees);
props.handleEmployeeChange(tableEmployees);
setrefresher(!refresher)
}
return(
<div>
<Table style={{width:'25%'}} aria-label="projects table">
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell align="right">Hours</TableCell>
<TableCell align="right">Delete</TableCell>
</TableRow>
</TableHead>
<TableBody>
{employees.map((employee) => (
<TableRow key={employee.employeeID}>
<TextField
variant='outlined'
value={employee.employeeID}
onChange={(event) => handleIdChange(employee.employeeID,event)}
style={{marginTop:`0px`,float:`right`}}
margin='dense'
InputProps={{
style:{fontSize:`1rem`},}}
/>
<TableCell align="right">
<Fab color="secondary" aria-label="delete user" onClick={handleDelete.bind(this,employee.employeeID)}>
<DeleteIcon />
</Fab>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<Fab color="primary" aria-label="add employee" variant="extended" onClick={handleAddEmployee}>
<AddIcon />
Add employee
</Fab>
</div>
)
}
ProjectDetails:
const ProjectDetails = props => {
const classes = useStyles();
const {
selectedProject,setSelectedProject,setSelectedOption
} = props
const [projects,setProjects] = useState(JSON.parse(localStorage.getItem(`projects`)))
const [id,setId] = useState('');
const [description,setDescription] = useState('');
const [name,setName] = useState('');
function findProject(project) {
return project.id === selectedProject;
}
const [employees,setEmployees] = useState([]);
useEffect( () => {
if(selectedProject)
{
const projectIndex =projects.findIndex(findProject);
setId(projects[projectIndex].id);
setDescription(projects[projectIndex].description)
setName(projects[projectIndex].name)
setEmployees(projects[projectIndex].employees)
}
},[])
const handleIdChange = event => {
setId(event.target.value)
}
const handleNameChange = event => {
setName(event.target.value)
}
const handleDelete= event => {
const projectIndex =projects.findIndex(findProject);
projects.splice(projectIndex,1);
localStorage.setItem(`projects`,JSON.stringify(projects));
setProjects(projects);
setSelectedOption(1);
};
const handleDescriptionChange = event => {
setDescription(event.target.value)
}
const handleEmployeeChange = employees => {
setEmployees(employees)
}
const handleSave = e => {
e.preventDefault()
const newProject = {
id,name,description,employees,}
var newProjects=projects;
if(newProjects===null)
newProjects=[newProject];
else if(selectedProject)
{
const projectIndex =projects.findIndex(findProject);
newProjects.splice(projectIndex,1);
newProjects.push(newProject);
}
else
newProjects.push(newProject);
localStorage.setItem(`projects`,JSON.stringify(newProjects));
setSelectedProject(null);
setProjects(newProjects);
setSelectedOption(1);
}
return(
<div style={{width:`25%`}}>
<div style={{height:`44px`}}>
<Typography variant='h6' edge='start' style={{display:`inline`}}>
ID:
</Typography>
<TextField
variant='outlined'
value={id}
onChange={handleIdChange}
style={{marginTop:`0px`,}}
/>
</div>
<div style={{height:`44px`}}>
<Typography variant='h6' edge='start' style={{display:`inline`}}>
Name:
</Typography>
<TextField
variant='outlined'
value={name}
onChange={handleNameChange}
style={{marginTop:`0px`,}}
/>
</div>
<div style={{height:`44px`}}>
<Typography variant='h6' edge='start' style={{display:`inline`}}>
Description:
</Typography>
<TextField
value={description}
onChange={handleDescriptionChange}
variant='outlined'
style={{marginTop:`0px`,}}
/>
</div>
<ProjectEmployeesTable employees={employees} handleEmployeeChange={handleEmployeeChange} />
<Fab color='primary' aria-label='save project' variant='extended' onClick={handleSave}>
<SaveIcon /> Save project
</Fab>
<Fab color="secondary" aria-label="delete user" variant="extended" onClick={handleDelete}>
<DeleteIcon />
Delete project
</Fab>
</div>
)
}