get
함수는 selector가 값을 계산하고 가져오는 데 사용한다.
set
함수는 selector가 상태를 변경하거나 업데이트 하는데 사용한다.
Selector의 get
export const minuteState = atom({
key:"minutes",
default: 0,
})
export const hourSelector = selector({
key: "hours",
get: ({get})=>{
const minutes = get(minuteState);
return minutes/60;
}
})
위 예제에서 hourSelector
는 minuteState
라는 다른 Recoil 상태를 읽어와서 분을 시간으로 바꿔주는 selector 이다.
get
useRecoilValue
나 useRecoilValueLoadable
등을 통해 get
함수를 사용하여 상태 값을 조회합니다.이후 컴포넌트에서 다음과 같이 사용할 수 있다.
const [minutes, setMinutes] = useRecoilState(minuteState);
const hours = useRecoilValue(hourSelector);
Selector의 set
: selector을 통해 파생된 상태 값을 변경하고 업데이트 하는데 사용된다.
Recoil의 상태 업데이트를 처리하고 외부에서 selector값을 변경할 수 있다.
export const hourSelector = selector<number>({
key: "hours",
get: ({get})=>{
const minutes = get(minuteState);
return minutes/60;
},
set: ({set}, newValue)=>{
const minutes = Number(newValue) * 60;
set(minuteState, minutes);
}
})
const [hours, setHours] = useRecoilState(hourSelector);
const onHoursChange = (event: React.FormEvent<HTMLInputElement>) => {
setHours(+event.currentTarget.value);
//javascript 개념: +는 string을 number로 바꿔준다.
};
return(
<>
<input
value={minutes}
onChange={onMinutesChange}
type="number"
placeholder="Minutes"
/>
<input
value={hours}
onChange={onHoursChange}
type="number"
placeholder="Hours"
/>
</>
)
set
set
함수는 상태를 업데이트하기 위해 사용.useRecoilState
나 useSetRecoilState
를 통해 set
함수를 사용하여 상태를 업데이트.npm i react-beautiful-dnd
npm i --save -dev @types/react-beautiful-dnd
draggbleProps
: 드래그 가능한 요소 자체를 다룸.
dragHandleProps
: 해당 요소 내에서 실제 드래그를 수행하는 핸들을 다루는 것.
magic.placeholder
유무에 따라서 리스트를 빼고 넣을 때 사이즈 조절유무가 결정된다.
:magic.placeholder
를 사용하면 드래그 중인 아이템이 미리 예상된 위치에 적절한 공간을 확보하여, 사용자에게 어떤 위치에 드롭될 것인지 시각적으로 표시.
onDragEnd
함수는 react-beautiful-dnd에서 제공하는 필수prop이다.
다음 코드를 사용하면 onDragEnd
가 뭐를 주는지 알 수 있다.
const onDragEnd = (args:any) =>{
console.log(args);
}
재정렬의 핵심 splice
splice을 이용하여 배열을 자르자.
ex> 배열에서 index 0 을 지우고 싶다고 가정
const x= ["a",
x.splice(0, 1)
// : const x = ["b","c","d","e"];
ex> a를 index 3에 넣고 싶다고 가정
x.splice(3, 0, "a")
// 3번째에, 0: 아무것도 지우지 않고, "a"를 넣고 싶다.
mutation
: 원본 값을 변경하는 작업
non-mutation
: 데이터의 원본 값을 변경하지 않고 새로운 값을 반환하는 작업
source.index에 위치한 요소를 삭제하고,
그 자리에 draggableId을 추가한다.
const copyToDos = [...oldToDos];
copyToDos.splice(source.index, 1);
copyToDos.splice(destination?.index, 0, draggableId);
return copyToDos;
function DraggableCard({toDo, index}:IDraggableCardProps) {
return (
<Draggable key={toDo} draggableId={toDo} index={index}>
{(magic) => (
<Card
ref={magic.innerRef}
{...magic.dragHandleProps}
{...magic.draggableProps}
>
{toDo}
</Card>
)}
</Draggable>
);
}
react-beautiful-dnd
라이브러리에서 key
값과 draggableId
값을 똑같이 사용하는 이유는 key
값이 React에서 컴포넌트 리스트를 렌더링할 때 각 아이템을 구분하기 위한 고유한 식별자이고, draggableId
는 해당 드래그 가능한 아이템을 식별하기 위한 값.
둘 다 아이템의 고유성을 보장하고 각각의 역할을 수행.
이 두 값을 동일하게 설정하는 것은 아래와 같은 이유로 유용합니다:
key
값과 draggableId
값을 동일하게 설정함으로써 각 아이템이 고유하게 식별되도록 보장합니다. React에서 컴포넌트 리스트를 렌더링할 때 key
값은 각 아이템을 식별하고 업데이트를 최적화하는 데 사용되므로, draggableId
와 key
값을 동일하게 설정하면 두 값이 항상 일치하며 고유성이 유지.key
값과 draggableId
값을 동일하게 설정하면 React가 아이템의 변경 상태를 더 정확하게 추적할 수 있습니다. 이로써 불필요한 리렌더링을 최소화하고 더 나은 성능을 얻을 수 있다.따라서 react-beautiful-dnd
에서는 이러한 이유로 일반적으로 key
값과 draggableId
값을 똑같이 설정하는 것이 좋다.
이렇게 하면 아이템의 고유성을 보장하며 퍼포먼스도 최적화 가능.
react memo : prop이 바뀌지 않는다면 컴포넌트를 렌더링 하지 말라고 한다.
prop이 변하지 않았다면 DraggableCard를 다시 렌더링 하지 마라.
export default React.memo(DraggableCard);
Object 반복 돌리기
const test = {
x: ["1","2"],
y: ["3","4"]
}
Object.keys(test);
Obeject.values(test);
Object.keys(test).map(testNum => test[testNum])
멀티보드 만들고 나서, 같은 보드내에서의 이동
: destination?.droppableId === source.droppableId (같은 보드내에서의 이동)
allBoards → toDoState라고 보면 된다.
const onDragEnd=(info:DropResult) =>{
console.log(info);
const {destination, draggableId, source} = info;
if(destination?.droppableId === source.droppableId){
setToDos((allBoards)=>{
const boardCopy = [...allBoards[source.droppableId]];
boardCopy.splice(source.index, 1);
boardCopy.splice(destination?.index, 0, draggableId);
return{
...allBoards,
[source.droppableId]: boardCopy,
};
});
}
};
interface IToDoState{
[key:string] : string[];
}
export const toDoState = atom<IToDoState>({
key:"toDo",
default:{
ToDo: ["이","것"],
Doing: ["은","기","본"],
Done: ["임"],
},
})