위로 / 아래로 버튼을 눌러서 순서 변경!!

import { useState } from "react";
import { MOCK_DATA } from "./MOCK_DATA.js";
const ChangeListOrder = () => {
const [pokemonData, setPokemonData] = useState(MOCK_DATA);
// TODO '위로' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 첫 번째 아이템은 위로 이동 할 수 없음을 기억해주세요!
const moveItemUp = (i) => {
if (i === 0) return;
setPokemonData((prevPokemonData) => {
const newPokemonData = [...prevPokemonData];
[newPokemonData[i - 1], newPokemonData[i]] = [
newPokemonData[i],
newPokemonData[i - 1],
];
return newPokemonData;
});
};
// TODO '아래' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 마지막 아이템은 아래로 이동 할 수 없음을 기억해주세요!
const moveItemDown = (i) => {
if (i === pokemonData.length - 1) return;
setPokemonData((prevPokemonData) => {
const newPokemonData = [...prevPokemonData];
[newPokemonData[i], newPokemonData[i + 1]] = [
newPokemonData[i + 1],
newPokemonData[i],
];
return newPokemonData;
});
};
return (
<div className="container mx-auto">
<h2 className="w-full text-center py-10">리스트 순서 바꾸기</h2>
<div className="flex flex-col gap-2">
{/* TODO Index 도 필요하다면, 수정해주세요 */}
{pokemonData.map((pokemon, index) => (
<div
key={index}
className="pokemon p-4 border rounded-lg flex justify-between"
>
<div>
<img
src={pokemon.sprites.front_default}
alt={pokemon.korean_name}
/>
<p>{pokemon.korean_name}</p>
<p>도감번호: {pokemon.id}</p>
</div>
<div className="flex gap-5 items-center">
{/* TODO moveItemUp 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
<button
className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={() => moveItemUp(index)}
>
위로
</button>
{/* TODO moveItemDown 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
<button
className="bg-state-warning h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={() => moveItemDown(index)}
>
아래로
</button>
</div>
</div>
))}
</div>
</div>
);
};
export default ChangeListOrder;
[수정] -> 수정 화면으로 변경
[위로] / [아래로] 버튼을 눌러서 순서 변경
[완료] -> 변경된 순서로 저장
[취소] -> [수정] 누르기 전 상태로 되돌아감

import { useState } from "react";
import { MOCK_DATA } from "./MOCK_DATA.js";
const ChangeListOrderAdvanced = () => {
const [pokemonData, setPokemonData] = useState(MOCK_DATA);
const [isEditMode, setIsEditMode] = useState(false);
const [editedPokemonData, setEditedPokemonData] = useState([...pokemonData]);
// TODO '위로' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 첫 번째 아이템은 위로 이동 할 수 없음을 기억해주세요!
const moveItemUp = (i) => {
if (i === 0) return;
setEditedPokemonData((prevPokemonData) => {
const newPokemonData = [...prevPokemonData];
[newPokemonData[i - 1], newPokemonData[i]] = [
newPokemonData[i],
newPokemonData[i - 1],
];
return newPokemonData;
});
};
// TODO '아래' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 마지막 아이템은 아래로 이동 할 수 없음을 기억해주세요!
const moveItemDown = (i) => {
if (i === pokemonData.length - 1) return;
setEditedPokemonData((prevPokemonData) => {
const newPokemonData = [...prevPokemonData];
[newPokemonData[i], newPokemonData[i + 1]] = [
newPokemonData[i + 1],
newPokemonData[i],
];
return newPokemonData;
});
};
// TODO 변경 완료가 되었을 떄 로직을 작성해 주세요.
const handleSubmit = () => {
setPokemonData(editedPokemonData);
setIsEditMode(false);
};
const toggleEditMode = () => {
setIsEditMode((prevState) => {
if (prevState) {
setPokemonData(pokemonData);
}
return !prevState;
});
};
return (
<div className="container mx-auto">
<h2 className="w-full text-center py-10">리스트 순서 바꾸기</h2>
<div className="flex gap-2 justify-end pb-4">
{isEditMode ? (
<>
{/* TODO 취소가 눌렸을 때 단순히, toggleEdit 을 불러주기 싫을 수도 있을 것 같아요. 마음대로 리팩토링 하셔도 됩니다. */}
<button
className="bg-state-error h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={toggleEditMode}
>
취소
</button>
{/* TODO 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
<button
className="bg-section h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={() => {
handleSubmit();
}}
>
완료
</button>
</>
) : (
<button
className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={toggleEditMode}
>
수정
</button>
)}
</div>
<div className="flex flex-col gap-2">
{/* TODO Index 도 필요하다면, 수정해주세요 */}
{editedPokemonData.map((pokemon, index) => (
<div
key={index}
className="pokemon p-4 border rounded-lg flex justify-between"
>
<div>
<img
src={pokemon.sprites.front_default}
alt={pokemon.korean_name}
/>
<p>{pokemon.korean_name}</p>
<p>도감번호: {pokemon.id}</p>
</div>
{isEditMode ? (
<div className="flex gap-5 items-center">
{/* TODO moveItemUp 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
<button
className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={() => moveItemUp(index)}
>
위로
</button>
{/* TODO moveItemDown 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
<button
className="bg-state-warning h-10 p-2 rounded text-[#ffffff] font-bold"
onClick={() => moveItemDown(index)}
>
아래로
</button>
</div>
) : null}
</div>
))}
</div>
</div>
);
};
export default ChangeListOrderAdvanced;
지금 작은 사이드 프로젝트 기획 중인데, 딱 적용하기 좋은 문제였다.
사이드 프로젝트에선 버튼 클릭 대신 블록을 끌어서 순서를 바꿀 수 있는 로직을 구현해볼 계획이다.