React-Typescript 编辑列表

React-Typescript edit list

我正在使用 React-TypeScript 创建员工列表,编辑和删除它们。但是我的编辑按钮在点击时没有做任何事情。知道如何解决这个问题吗?

我对“删除”功能使用了相同的代码并且运行良好。以下是我的两个 react-typescript 文件,我在其中编写了我的代码,我还有一个 app.tsx 文件,所有这些都被导入其中。

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;

您正在其 setter 中使用当前状态的值 employeeList。而不是将对象传递给 useStateyou can pass a function instead that takes the old state as a parameter。例如:

setEmployeeList((oldEmployeeList) => 
      (oldEmployeeList.map((employee) => {
        if (employee.employeeName === employeeNameToEdit) {
          employee.employeeId = employeeIdToEdit;
        }
        return employee;
      }))
    );

这是状态突变的问题,您正在突变正在编辑的员工对象,而不是返回 new 员工对象引用.由于特定的 employee 对象引用没有改变,React 可能会放弃重新渲染它们,因为它在协调期间使用浅引用相等性检查。

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

问题不在于你改变了状态,你的 editEmployee 函数正确地使用了 setEmployeeList -- map returns 一个新数组,而 React 是检测此更改并重新渲染组件。您可以通过将 console.log('rendering'); 插入 CreateEmployee 函数来验证这一点。

问题是 editEmployee 只是创建了旧 employeeList 的精确副本。

您可能想要它做的是用编辑后的员工 ID 和姓名填充文本字段,然后在单击提交按钮时更新您的员工列表。

const editEmployee = (
    employeeNameToEdit: string,
    employeeIdToEdit: string
  ): void => {
    // This will put these two items into the text fields for editing
    setEmployeeId(employeeIdToEdit);
    setEmployeeName(employeeNameToEdit);
  };

并将 addEmployee 更改为如下内容(您可以将其重命名为 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('');
  };

决定它是新员工还是编辑员工的逻辑完全是我的,您应该使用适合您的应用程序的任何内容。