#7.4 Styles and Placeholders #7.5 Reordering #7.6 Reordering part Two #7.7 Performance #7.9 Same Board Movement #7.10 Cross Board #7.11 Droppable Snapshot

SilverAsh·2023년 10월 29일
0

React

목록 보기
16/16

magic.placeholder let the Droppable Board keep the original size.
onDrag는 드래그가 끝났을 때 실행될 함수를 arg로 받는다 & gives many information about what happend when the drag finished

import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import styled from "styled-components";

const Wrapper = styled.div`
display: flex;
max-width: 480px;
width:100%;
margin: 0 auto;
justify-content: center;
align-items: center;
height:100vh;
`
const Boards = styled.div`
  display: grid;
  width:100%;
  grid-template-columns:  repeat(1, 1fr);
`
const Board = styled.div`
  padding: 20px 10px;
  padding-top:30px;
  background-color: ${props => props.theme.boardColor};
  border-radius: 5px;
  min-height:200px;

`
const Card = styled.div`
  background-color: ${props => props.theme.cardColor};
  padding: 5px 10px;
  margin-bottom:5px;
  border-radius: 5px;
`;
const toDos = ["a", "b", "c", "d", "e", "f"];

function App() {
  const onDragEnd = () => { }
  return <DragDropContext onDragEnd={onDragEnd}>
    <Wrapper>
      <Boards>
        <Droppable droppableId="one">
          {(magic) =>
            <Board ref={magic.innerRef} {...magic.droppableProps}>
              {toDos.map((toDo, index) => <Draggable draggableId={toDo} index={index} key={index}>
                {(magic) => (<Card
                  ref={magic.innerRef}
                  {...magic.draggableProps}{...magic.dragHandleProps}
                >
                  {toDo}
                </Card>)}
              </Draggable>)}
              {magic.placeholder}
            </Board>}
        </Droppable>
      </Boards>
    </Wrapper>
  </DragDropContext >
}
export default App;
import { atom, selector } from "recoil";

export const toDoState = atom({
    key: "toDo",
    default: ["a", "b", "c", "d", "e", "f"],
})

todos( ["a", "b", "c", "d", "e", "f"])를 가지고 있는데 이것으로 두 단게를 거쳐 볼 것이다~.
1. source.array 로부터 index를 삭제할 것이다!

array.splice(a,b) => array의 a인덱스부터 b개 만큼 삭제한다.
array.splice(a, 0, c) => array의 a인덱스부터 0개(아무것도 지우지 않고)를 지우고, c를 삽입한다.

key & draggableId must be the same

 const onDragEnd = ({ draggableId, destination, source }: DropResult) => {
    if (!destination) return;

    setToDos(oldToDos => {
      const copyToDos = [...oldToDos];
      // 1) Delete item on source.index
      copyToDos.splice(source.index, 1)
      // 2) Put back the item on the destination.index
      copyToDos.splice(destination?.index, 0, draggableId)
      return copyToDos;
    })
  }

Object.keys => 키들을 배열로 반환하여 준다.
!destination은 옮기지 않았을 때의 경우.
useRecoilState의 함수를 사용하여 바뀐 순서를 다시 저장한다.
이 때 사용할 속성들(draggableId, destination, source)은 DropResult에서 가져올 수 있다.

react memeo => allow react.js please not to rerender this component if the props didn't change

사용법
원래 export default DraggableCard => export default React.memo(DraggableCard)

3개의 보드 만들기

  1. atom 수정
  2. 컴포넌트 분리
  3. Object.keys(toDos).map(boardId => toDos[boardId])

interface 설정을 해주지 않으면 typescript가 저 세가지 유형만 허용하기때문에 다른 key도 차후에 들어올수 있게 하려면 저렇게 interface를 만들어 설정해 주어야 한다.

interface IToDoState {
    [key: string]: string[];
}
export const toDoState = atom<IToDoState>({
    key: "toDo",
    default: {
        to_do: ["a", "b",],
        doing: ["c", "d", "e"],
        done: ["f"],
    },
})

1) make a copy only of a array that happened modifying
2) then we put that copy next to the older things

 const [toDos, setToDos] = useRecoilState(toDoState);
  const onDragEnd = (info: DropResult) => {
    console.log(info);
    const { destination, draggableId, source } = info;
    if (!destination) return;
    if (destination?.droppableId === source.droppableId) {
      //same board movement
      setToDos((allBoards) => {
        //allBoards is not array anymore
        //copy only the board that changed
        //when we return, must return boardCopy and previous states of other Boards
        const boardCopy = [...allBoards[source.droppableId]];
        boardCopy.splice(source.index, 1)
        boardCopy.splice(destination?.index, 0, draggableId)
        return {
          ...allBoards,
          [source.droppableId]: boardCopy
        };

      })
    }
    if (destination.droppableId !== source.droppableId) {
      // cross board movement
      setToDos(allBoards => {
        const sourceBoard = [...allBoards[source.droppableId]];
        const destinationBoard = [...allBoards[destination.droppableId]];
        sourceBoard.splice(source.index, 1);
        destinationBoard.splice(destination?.index, 0, draggableId);
        return {
          ...allBoards,
          [source.droppableId]: sourceBoard,
          [destination.droppableId]: destinationBoard
        }
      })
    }
  }

움직이기 편하게 하기위해서는 receiver의 크기 도 중요함

Changing Color depending on leaving or arriving

=> requires another argument(other tahn magic(which is provided)) : snapshot tells that if the user is draggingFrom(leave) or draggingOver(arrive)

interface IAreaProps {
    isDraggingOver: boolean;
    DraggingFromThisWith: boolean;
}
const Area = styled.div <IAreaProps> `
    background-color: ${props => props.isDraggingOver ? "pink" : props.DraggingFromThisWith ? "red" : "blue"};
    flex-grow:1;
    height: 100%;
`
function Board({ toDos, boardId }: IBoardProps) {
    return (
        <Wrapper>
            <Title>{boardId}</Title>
            <Droppable droppableId={boardId}>
                {(magic, snapshot) =>
                    <Area isDraggingOver={snapshot.isDraggingOver}
                        DraggingFromThisWith={Boolean(snapshot.draggingFromThisWith)} ref={magic.innerRef} {...magic.droppableProps}>
                        {toDos.map((toDo, index) => <DraggableCard key={toDo} toDo={toDo} index={index} />
                        )}
                        {magic.placeholder}
                    </Area>}
            </Droppable>
        </Wrapper>
    )
}
profile
Frontend developer이자

0개의 댓글