This is a simple form table with two states - one (employees
) is to keep track of the updated form value, and the other (records
) should have saved the form values only when the add/save button is clicked.
The issue is that whenever handleChange
is called, it starts to update both the states, which is very weird since setRecords
is not called in there.
what am I doing wrong that causes the two states to change together?
I suspect that it has something to do with how I initialized the two states here. What is the correct way to do it then?
const [employees, setEmployees] = useState([...initialValues, emptyRow] || []);
const [records, setRecords] = useState([...initialValues] || []);
Full codes are here:
import { useState } from "react";
import "./App.css";
const initialValues = [
{
id: 1,
name: "John",
position: "Developer",
salary: 50000,
isUpdated: false,
},
{
id: 2,
name: "Jane",
position: "Designer",
salary: 60000,
isUpdated: false,
},
{
id: 3,
name: "Bob",
position: "Manager",
salary: 70000,
isUpdated: false,
},
];
const emptyRow = {
id: 0,
name: "",
position: "",
salary: 0,
isUpdated: false,
};
const headings = ["Name", "Position", "Salary", "Action"];
const Employee = ({ employee, handleChange, handleClick }) => (
<tr key={employee.id}>
<td>
<input
type="text"
id="name"
name="name"
onChange={(e) => handleChange(e, employee.id)}
value={employee.name}
disabled={employee.id !== 0}
/>
</td>
<td>
<input
type="text"
id="position"
name="position"
onChange={(e) => handleChange(e, employee.id)}
value={employee.position}
disabled={employee.id !== 0}
/>
</td>
<td>
<input
type="number"
id="salary"
name="salary"
onChange={(e) => handleChange(e, employee.id)}
value={employee.salary ? employee.salary : ""}
/>
</td>
<td>
<button onClick={() => handleClick(employee.id)}>{employee.id !== 0 ? "Save" : "Add"}</button>
</td>
</tr>
);
function App() {
const [employees, setEmployees] = useState([...initialValues, emptyRow] || []);
const [records, setRecords] = useState([...initialValues] || []);
const handleClick = (id) => {
const foundEmp = employees.find((x) => x.id === id);
const foundRec = records.find((x) => x.id === id);
console.log(`------- foundEmp :`, JSON.stringify(foundEmp, null, 2));
console.log(`------- foundRec :`, JSON.stringify(foundRec, null, 2));
};
const handleChange = (e, id) => {
const k = e.target.name;
const v = e.target.value;
const updated = employees.map((emp) => {
if (emp.id === id) {
emp[k] = v;
}
return emp;
});
setEmployees([...updated]);
};
return (
<div className="App">
<form onSubmit={(e) => e.preventDefault()}>
<table width="100%" data-testid="table">
<tbody>
<tr>
{headings?.map((h, i) => (
<th key={i}>{h}</th>
))}
</tr>
{employees.map((employee) => (
<Employee employee={employee} handleChange={handleChange} handleClick={handleClick} />
))}
</tbody>
</table>
</form>
</div>
);
}
export default App;