React_Todo(ft.Recoil):01

김정훈·2023년 8월 25일
0
post-thumbnail

Selector의 Get,Set

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;
    }
})

위 예제에서 hourSelectorminuteState라는 다른 Recoil 상태를 읽어와서 분을 시간으로 바꿔주는 selector 이다.
get

  • 상태를 읽기 위해 사용.
  • 읽기 작업에만 관여하며, 상태 값을 조회하는 것만으로는 상태 변경에 대한 추적이나 리렌더링을 트리거하지 않음.
  • useRecoilValueuseRecoilValueLoadable 등을 통해 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 함수는 상태를 업데이트하기 위해 사용.
  • Recoil 상태 값을 변경하고 업데이트할 때 사용.
  • useRecoilStateuseSetRecoilState를 통해 set 함수를 사용하여 상태를 업데이트.

Drag and Drop(react-beautiful-dnd)

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;

이 코드에서 key값과 draggableId값을 동일하게 사용하는 이유

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는 해당 드래그 가능한 아이템을 식별하기 위한 값.
둘 다 아이템의 고유성을 보장하고 각각의 역할을 수행.

이 두 값을 동일하게 설정하는 것은 아래와 같은 이유로 유용합니다:

  1. 고유성 보장: key 값과 draggableId 값을 동일하게 설정함으로써 각 아이템이 고유하게 식별되도록 보장합니다. React에서 컴포넌트 리스트를 렌더링할 때 key 값은 각 아이템을 식별하고 업데이트를 최적화하는 데 사용되므로, draggableIdkey 값을 동일하게 설정하면 두 값이 항상 일치하며 고유성이 유지.
  2. 더 나은 퍼포먼스: key 값과 draggableId 값을 동일하게 설정하면 React가 아이템의 변경 상태를 더 정확하게 추적할 수 있습니다. 이로써 불필요한 리렌더링을 최소화하고 더 나은 성능을 얻을 수 있다.

따라서 react-beautiful-dnd에서는 이러한 이유로 일반적으로 key 값과 draggableId 값을 똑같이 설정하는 것이 좋다.
이렇게 하면 아이템의 고유성을 보장하며 퍼포먼스도 최적화 가능.


React memo

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: ["임"],
    },
})
profile
WebDeveloper

0개의 댓글