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
。而不是将对象传递给 useState
、you 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('');
};
决定它是新员工还是编辑员工的逻辑完全是我的,您应该使用适合您的应用程序的任何内容。
我正在使用 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
。而不是将对象传递给 useState
、you 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('');
};
决定它是新员工还是编辑员工的逻辑完全是我的,您应该使用适合您的应用程序的任何内容。