I am using React-TypeScript to create a list of employees, edit and delete them. However my edit button does not do anything on click. Any idea on how I can fix this problem?
I have used the same code for the "Delete" function and works perfectly. Following are my two react-typescript files which I have my codes written in and I also have an app.tsx file which all of these are being imported in it.
CreateEmployee.tsx
import React, { useState, FC, ChangeEvent } from "react";
import { Link } from "react-router-dom";
import { IEmployee } from "../../Interfaces";
import EmployeeList from "./EmployeeList";
export const CreateEmployee: FC = () => {
const [employeeName, setEmployeeName] = useState<string>("");
const [employeeId, setEmployeeId] = useState<any>("");
const [employeeList, setEmployeeList] = useState<IEmployee[]>([]);
// get the data from the input and add it to the state
const handleChange = (event: ChangeEvent<HTMLInputElement>): void => {
if (event.target.name === "employeename") {
setEmployeeName(event.target.value);
} else {
setEmployeeId(event.target.value);
}
};
// add id and name to the employee list
const addEmployee = (): void => {
const newEmployee = {
employeeId: employeeId,
employeeName: employeeName,
};
setEmployeeList([...employeeList, newEmployee]);
setEmployeeName("");
setEmployeeId("");
};
// delete employee from the list
const deleteEmployee = (employeeNameToDelete: string): void => {
setEmployeeList(
employeeList.filter(
(employee) => employee.employeeName !== employeeNameToDelete
)
);
};
// edit employee name and id in the list
const editEmployee = (
employeeNameToEdit: string,
employeeIdToEdit: string
): void => {
setEmployeeList(
employeeList.map((employee) => {
if (employee.employeeName === employeeNameToEdit) {
employee.employeeId = employeeIdToEdit;
}
return employee;
})
);
};
return (
<div>
<h1>Create Employee</h1>
<div>
<label>Employee Id:</label>
<input
type="text"
name="employeeid"
value={employeeId}
onChange={(e) => setEmployeeId(e.target.value)}
/>
<label>Employee Name:</label>
<input
type="text"
name="employeename"
value={employeeName}
onChange={(e) => setEmployeeName(e.target.value)}
/>
<button type="submit" onClick={addEmployee}>
Submit
</button>
</div>
<div>
<Link to="/employeelist">Employee List</Link>
<Link to="/engagementList">Engagement List</Link>
</div>
<div className="employee-list">
<h1>Employee List</h1>
{employeeList.map((employee: IEmployee, key: number) => {
return (
<EmployeeList
key={key}
employee={employee}
deleteEmployee={deleteEmployee}
editEmployee={editEmployee}
/>
);
})}
</div>
</div>
);
};
EmployeeList.tsx
import React from "react";
import { IEmployee } from "../../Interfaces";
import { CreateEmployee } from "../employeeComponents/CreateEmployee";
interface Props {
employee: IEmployee;
deleteEmployee: (employeeNameToDelete: string) => void;
editEmployee: (employeeNameToEdit: string, employeeIdToEdit: string) => void;
}
export const EmployeeList = ({ employee, deleteEmployee, editEmployee }: Props) => {
return (
<div>
<div className="employee-list">
<div className="content">
<span>{employee.employeeId}</span>
<span>{employee.employeeName}</span>
</div>
<button
onClick={() => {
deleteEmployee(employee.employeeName);
}}
>
Delete
</button>
<button
onClick={() => {
editEmployee(employee.employeeName, employee.employeeId);
}}
>
Edit
</button>
</div>
</div>
);
};
export default EmployeeList;
CodePudding user response:
You are using the current state's value employeeList
within its setter. Instead of passing an object to useState
, you can pass a function instead that takes the old state as a parameter. For example:
setEmployeeList((oldEmployeeList) =>
(oldEmployeeList.map((employee) => {
if (employee.employeeName === employeeNameToEdit) {
employee.employeeId = employeeIdToEdit;
}
return employee;
}))
);
CodePudding user response:
This is an issue of state mutation, you are mutating the employee object you are editing instead of returning a new employee object reference. Since the specific employee
object reference doesn't change React is likely bailing on rerendering them since it uses shallow reference equality checks during Reconciliation.
const editEmployee = (
employeeNameToEdit: string,
employeeIdToEdit: string
): void => {
setEmployeeList(employeeList => employeeList.map((employee) => {
if (employee.employeeName === employeeNameToEdit) {
return { // <-- return new object reference
...employee, // <-- shallow copy previous state
employeeId: employeeIdToEdit, // <-- set property value
}
}
return employee; // <-- else return previous state
}));
};