I would like to increment salary number inside map function.
My code is currently working but I would like to know is this a correct way to increment number in React or what is the better method or how else should I do it?
find below the code so far
const users = [
{
id: 1,
name: "Tiger Nixon",
salary: 320800,
age: 61,
},
{
id: 2,
name: "Garrett Winters",
salary: 170750,
age: 63,
},
{
id: 3,
name: "Ashton Cox",
salary: 86000,
age: 66,
},
{
id: 4,
name: "Cedric Kelly",
salary: 433060,
age: 22,
}
]
const [salary, setSalary] = useState(users)
const incrementSalary = (employeeSalary) => {
salary.map(x =>
x.salary === employeeSalary? {...salary, salary : x.salary = 1} : x
)
setSalary([...salary])
}
return (
<tbody>
{salary.map((employee) => (
<tr key={employee.id}>
<th>{employee.id}</th>
<td>{employee.name}</td>
<td>{employee.age}</td>
<td>
<button>
-
</button>
<span>{employee.salary}</span>
<button onClick={() => incrementSalary(employee.salary)}>
</button>
</td>
</tr>
)}
</tbody>
CodePudding user response:
No, doing x.salary = 1
mutates the existing state.
The correct way is to apply the immutable update patten: shallow copy all state, and nested state, that is being updated. You should also use a functional state update to correctly update from the previous state instead of whatever the current state value is that is closed over in callback scope.
You will also want to use an id or some other GUID to uniquely identify the employee element object you want to increment the salary property of.
Example:
const incrementSalary = (employeeId) => {
setSalary(salary => salary.map(employee =>
employee.id === employeeId
? {
...salary,
salary: employee.salary 1
}
: x
));
};
...
{salary.map((employee) => (
<tr key={employee.id}>
<th>{employee.id}</th>
<td>{employee.name}</td>
<td>{employee.age}</td>
<td>
<button>-</button>
<span>{employee.salary}</span>
<button onClick={() => incrementSalary(employee.id)}>
</button>
</td>
</tr>
)}
CodePudding user response:
It's silly to map over the whole array to increment one number. map
takes a second parameter - the index of the array.
This is the 'proper' way with immutability.
const defaultUsers = [
{
id: 1,
name: 'Tiger Nixon',
salary: 320800,
age: 61,
},
{
id: 2,
name: 'Garrett Winters',
salary: 170750,
age: 63,
},
{
id: 3,
name: 'Ashton Cox',
salary: 86000,
age: 66,
},
{
id: 4,
name: 'Cedric Kelly',
salary: 433060,
age: 22,
},
];
export default function App() {
const [users, setUsers] = useState(defaultUsers);
const incrementSalary = (index) => {
setUsers((prevUsers) => {
const newUsers = [...prevUsers];
newUsers[index] = {
...newUsers[index],
salary: newUsers[index].salary 1,
};
return newUsers;
});
};
return (
<tbody>
{users.map((employee, index) => (
<tr key={employee.id}>
<th>{employee.id}</th>
<td>{employee.name}</td>
<td>{employee.age}</td>
<td>
<button>-</button>
<span>{employee.salary}</span>
<button onClick={() => incrementSalary(index)}> </button>
</td>
</tr>
))}
</tbody>
);
}
Stackblitz: https://stackblitz.com/edit/react-ts-a9rsnm?file=App.tsx
This is the faster way that gets you flamed by other React devs.
const defaultUsers = [
{
id: 1,
name: 'Tiger Nixon',
salary: 320800,
age: 61,
},
{
id: 2,
name: 'Garrett Winters',
salary: 170750,
age: 63,
},
{
id: 3,
name: 'Ashton Cox',
salary: 86000,
age: 66,
},
{
id: 4,
name: 'Cedric Kelly',
salary: 433060,
age: 22,
},
];
export default function App() {
const users = useRef(defaultUsers).current;
const [_, forceUpdate] = useReducer((x) => x 1, 0);
const incrementSalary = (index) => {
users[index].salary ;
forceUpdate();
};
return (
<tbody>
{users.map((employee, index) => (
<tr key={employee.id}>
<th>{employee.id}</th>
<td>{employee.name}</td>
<td>{employee.age}</td>
<td>
<button>-</button>
<span>{employee.salary}</span>
<button onClick={() => incrementSalary(index)}> </button>
</td>
</tr>
))}
</tbody>
);
}
Stackblitz: https://stackblitz.com/edit/react-ts-f3rvaa?file=App.tsx