Issue
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;
Solution
The problem was not that you were mutating the state, your editEmployee
function was using setEmployeeList
correctly -- map
returns a new array, and React was detecting this change and re-rendering the component. You can verify that by inserting console.log('rendering');
into your CreateEmployee
function.
The problem was that editEmployee
was just creating an exact copy of the old employeeList
.
What you probably want for it to do is to populate the text fields with the edited employee id and name, and then update your employee list when the submit button is clicked.
const editEmployee = (
employeeNameToEdit: string,
employeeIdToEdit: string
): void => {
// This will put these two items into the text fields for editing
setEmployeeId(employeeIdToEdit);
setEmployeeName(employeeNameToEdit);
};
and change addEmployee
to something like this (you may rename it to addOrUpdateEmployee
):
const addEmployee = (): void => {
const newEmployee = {
employeeId: employeeId,
employeeName: employeeName,
};
// Consider it's a new employee if the employee with this employeeId
// does not exist in the list of employees.
// Otherwise, it's an edited employee
let employeeIndex;
if (
employeeList.some((employee, index) => {
employeeIndex = index;
return employee.employeeId === employeeId;
})
) {
// This is not state mutation ...
employeeList[employeeIndex] = newEmployee;
// ...because we set it to a copy of the mutated array
setEmployeeList([...employeeList]);
} else {
setEmployeeList([...employeeList, newEmployee]);
}
setEmployeeName('');
setEmployeeId('');
};
The logic to decide if it's a new or edited employee is entirely mine, you should use whatever is appropriate for your app.
Answered By - tromgy
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.