I have the following code:
import React, { useState } from "react";
export default function App() {
const [arr, setArr] = useState([
{ id: 1, name: "orange" },
{ id: 2, name: "lemon" },
{ id: 3, name: "strawberry" },
{ id: 4, name: "apple" }
]);
const onMoveUp = function (key) {
if (key === 0) return;
const items = arr;
const index = key - 1;
const itemAbove = items[index];
items[key - 1] = items[key];
items[key] = itemAbove;
console.log(items);
setArr(items);
};
const onMoveDown = function (key) {
const items = arr;
if (key === items.length - 1) return;
const index = key 1;
const itemBelow = items[index];
items[key 1] = items[key];
items[key] = itemBelow;
setArr(items);
};
return (
<div>
<ul>
{arr.map((item, key) => (
<li key={key}>
<div>
{item.id} - {item.name}
</div>
<div>
<span onClick={() => onMoveUp(key)}>▲</span>
<span onClick={() => onMoveDown(key)}>▼</span>
</div>
</li>
))}
</ul>
</div>
);
}
What it is supposed to do is move list elements up and down using the arrows. I have tried many ways but nothing seems to work. I am currently exploring useEffect. The array does change but it is not reflected in the UI. Please help.
CodePudding user response:
In React, the UI must be changed to a new object in the state in order to be updated. A framework like React uses immutability for state management.
For example, in your function onMoveUp
, items
are the same array as arr
made with useState. React does not update the UI because you mutate the same object and store this value in the state.
Save the new object in the state by modifying the code as follows:
const onMoveUp = function (key) {
if (key === 0) return;
const items = [...arr]; // Create a new object with Copy Object
const index = key - 1;
const itemAbove = items[index];
items[key - 1] = items[key];
items[key] = itemAbove;
console.log(items);
setArr(items);
};
CodePudding user response:
It is not advisable to change the state value directly. It is better to make a copy of your state
Good learning
Here is an example with spread operator :
import React, { useState } from "react";
export default function App() {
const [arr, setArr] = useState([
{ id: 1, name: "orange" },
{ id: 2, name: "lemon" },
{ id: 3, name: "strawberry" },
{ id: 4, name: "apple" }
]);
const onMoveUp = function (key) {
if (key === 0) return;
const items = [...arr];
const index = key - 1;
const itemAbove = items[index];
items[key - 1] = items[key];
items[key] = itemAbove;
console.log(items);
setArr(items);
};
const onMoveDown = function (key) {
const items = [...arr];
if (key === items.length - 1) return;
const index = key 1;
const itemBelow = items[index];
items[key 1] = items[key];
items[key] = itemBelow;
setArr(items);
};
return (
<div>
<ul>
{arr.map((item, key) => (
<li key={key}>
<div>
{item.id} - {item.name}
</div>
<div>
<span onClick={() => onMoveUp(key)}>▲</span>
<span onClick={() => onMoveDown(key)}>▼</span>
</div>
</li>
))}
</ul>
</div>
);
}