Home > OS >  React-Typescript edit list
React-Typescript edit list

Time:12-02

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
  }));
};
  • Related