string 형태 number로 변경하기
setMinutes(+ event.currentTarget.value);
+"1"
Selector의 다른 속성 set
state를 set하는 걸 도와주는 속성
atom을 수정하는 것을 도와줌
const [] = useRecoilState는 배열을 받는데
selector를 useRecoilState로 받으면
첫번 째 array는 get property 에서 return 한 값.
두번 째는 set property를 부르는 함수 .
import { atom, selector } from "recoil";
export const minutesState = atom({
key: "minnutes",
default: 0,
});
export const hourSelector = selector<number>({ //atom을 각각 만들지않고mintues만 만들어서 값을 수정했다.
두개의 atom을 만들고 싶지 않다면 selector을 만들어서 수정하면됨
key: "hours",
get: ({ get }) => { //selector값을 어떻게 바꿀지
const min = get(minutesState);
return min / 60;
},
set: ({ set }, newValue) => { //atom을 수정하기 위해 selector을 어떻게 사용하는지
const minutes = Number(newValue) * 60;
set(minutesState, minutes);
},
});
set? - 이 속성이 설정되면 selector는 쓰기 가능한 상태를 반환한다.
react-beautiful-dnd
React로 list를 만들기 위한 아름답고 접근 가능한 드래그 앤 드롭
https://www.npmjs.com/package/react-beautiful-dnd
react-beautiful-dnd
Beautiful and accessible drag and drop for lists with React. Latest version: 13.1.0, last published: a year ago. Start using react-beautiful-dnd in your project by running `npm i react-beautiful-dnd`. There are 1286 other projects in the npm registry using
www.npmjs.com
필수 prop인 onDragEnd가 필요하다고함
드래그가 끝날 때 불려지는 함수
children이 필요하다고함
하위요소 span이든지, div든지 채워주면 애러가 사라짐
위와같이 하면서
첫번 째 argument provided
return (
<DragDropContext onDragEnd={onDragEnd}>
<div>
<Droppable droppableId="one">
{(magic) => (
<ul ref={magic.innerRef} {...magic.droppableProps}>
<Draggable draggableId="first" index={0}>
{(magic) => (
<li
ref={magic.innerRef}
{...magic.draggableProps}
{...magic.dragHandleProps}
>
one
</li>
)}
</Draggable>
<Draggable draggableId="second" index={1}>
{(magic) => (
<li
ref={magic.innerRef}
{...magic.draggableProps}
{...magic.dragHandleProps}
>
two
</li>
)}
</Draggable>
</ul>
)}
</Droppable>
</div>
</DragDropContext>
);
dragHandle 드래그 하는 손잡이
아무곳이나 누르면 움직이는 것이아니라
움직이는 손잡이만 따로 만들기
{(magic) => (
<li
ref={magic.innerRef}
{...magic.draggableProps}
>
<span {...magic.dragHandleProps}> 드래그 핸들프롭으 다른 곳에 위임함 이걸로만 드래그가능
🔥
</span>
one
</li>
)}
magic.placeholder
provided.placeholder (?ReactElement)
Draggable 엘리먼트를 드래그하는 동안 position: fixed(영역을 고정시킴)를 적용합니다.
Draggable을 드래그할 때 Droppable 리스트가 작아지는 것을 방지하기 위해 필요합니다.
Draggable 노드의 형제로 렌더링하는 것이 좋습니다.
provided
https://github.com/atlassian/react-beautiful-dnd/blob/HEAD/docs/api/droppable.md#1-provided-droppableprovided
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}>
{(magic) => (
<Card
ref={magic.innerRef}
{...magic.draggableProps}
{...magic.dragHandleProps}
>
{toDo}
</Card>
)}
</Draggable>
))}
{magic.placeholder}
</Board>
)}
</Droppable>
</Boards>
</Wrapper>
</DragDropContext>
아이템 드롭했을 때 재정렬하기
onDragEnd는 어떤 일이 일어났는지에 대한 정보로 많은 argument를줌
onDragEnd=(args:any)=>{console.log(args)};
destination과 source이용하려니까 typescript가 안맞다고 불평한다.
onDRagEnd를 눌러서 type 설명을보면 DropResult안에 destination 을 볼 수 있으니
({destination,source}:DropResult)로 타입 지정
array.splice 는 해당 배열을 mutate변화 시키는 동작이다.
atom state세계에서는 mutate하면 안돼
새로운 배열을 만들어서 수정.
+
주의점!
보통 react에서 key는 index를 입력하는데
beautiful dnd에서는 draggableId와 key내용이 같아야한다.
버그가 날 수 있으니 이 점 주의
< Draggable /> list의 키
< Draggable /> list를 렌더링하는 경우 각 < Draggable />에 key prop을 추가하는 것이 중요합니다.
규칙
key는 list 내에서 고유해야 합니다.
key에 item의 index가 포함되어서는 안 됩니다. (map의 index사용 X)
일반적으로 draggableId를 key로 사용하면 됩니다.
주의! list에 key가 없으면 React가 경고하지만 index를 key로 사용하는 경우 경고하지 않습니다.
key를 올바르게 사용하지 않으면 정말 안 좋은 일이 생길 수 있습니다 💥
```
return items.map((item, index) => (
< Draggable
// adding a key is important!
key={item.id}
draggableId={item.id}
index={index}
>
나머지 코드..
```
https://github.com/atlassian/react-beautiful-dnd/blob/HEAD/docs/api/draggable.md#keys-for-a-list-of-draggable-
GitHub - atlassian/react-beautiful-dnd: Beautiful and accessible drag and drop for lists with React
Beautiful and accessible drag and drop for lists with React - GitHub - atlassian/react-beautiful-dnd: Beautiful and accessible drag and drop for lists with React
github.com
재정렬 할 때 shaking 하는 현상 고치기
재정렬할때 [a,b,c,d,e,f] 중에 f->e로 움직이면
a부터 모든 요소들이 재정렬이된다.
이유는 react특성상 state가 바뀌면 다시 렌더링 되기때문에
부모가 바뀌면 자식이 바뀌고 그 자식, 자식도 다 바뀌는게 react
--> React memo
reat.js한테 prop이 변하지 않는다면 제발 이 components는 렌더링 하지 말라고 하는 역할을 함.
draggableCard에서 export default draagbleCard가 아니고
export default React.memo(DraggableCard);로 prop이 변하지 않았다면 draggableCard를 다시 렌더링하지 말라고 말함.
React.memo
React.memo는 고차 컴포넌트(Higher Order Component)입니다.
컴포넌트가 동일한 props로 동일한 결과를 렌더링해낸다면, React.memo를 호출하고 결과를 메모이징(Memoizing)하도록 래핑하여 경우에 따라 성능 향상을 누릴 수 있습니다. 즉, React는 컴포넌트를 렌더링하지 않고 마지막으로 렌더링된 결과를 재사용합니다.
React.memo는 props 변화에만 영향을 줍니다. React.memo로 감싸진 함수 컴포넌트 구현에 useState, useReducer 또는 useContext 훅을 사용한다면, 여전히 state나 context가 변할 때 다시 렌더링됩니다.
이 메서드는 오직 성능 최적화를 위하여 사용됩니다. 렌더링을 “방지”하기 위하여 사용하지 마세요. 버그를 만들 수 있습니다.
DraggableCard에게 동일한 index와 동일한 todo prop을 받으면 리랜더링을 하지 않도록 하기 위함이다.
```
function MyComponent(props) {
/* props를 사용하여 렌더링 */
}
export default React.memo(MyComponent, areEqual);
```
https://ko.reactjs.org/docs/react-api.html#reactmemo
React 최상위 API – React
A JavaScript library for building user interfaces
ko.reactjs.org
todo,doing,done세가지 보드로 나누기
세가지 보드로 나누기위하여 기존["a","b","c","d","e"];배열 형식에서
{ } object 형식으로 변경.
이 전에 사용했던 toDos.map()은 array에서만 사용가능
obejct loop처리하기
const toDos = {
x:["a","b"],
y:["c","d"]
}
object.keys(toDos) // ["x","y"] --.> boardID로 사용하면되겠다. 아래 참고
toDos["x"] // ["a","b"]
object.keys(toDos).map(boardId)-->toDos[boardId])
["x","y"] ["a","b"], ["c","d"]
===toDos["x"] , toDos["y"] / 같은결과
function Board({toDos, boardId}:IBoardProps) {
return (
<Droppable droppableId={boardId}> //
{(magic) => (
<Wrapper ref={magic.innerRef} {...magic.droppableProps}>
{toDos.map((toDo, index) => (
<DraggableCard key={toDo} index={index} toDo={toDo} />
))}
{magic.placeholder}
</Wrapper>
)}
</Droppable>
);
같은 보드 이동
oldToDos는 IToDoState를 보년 더 이상 array 구조가 아닌 object
[source.droppableId ] == ["doing"]
boardCopy should be an array.const boardCopy = oldToDossource.droppableId is not the same as: const boardCopy = [...oldToDossource.droppableId] 배열이여야지 Array.splice() 적용가능
마지막에 setTodos 함수에 인자로 디스트럭쳐링으로 oldTodos를 넣고 바뀐 board 프로퍼티를 더 넣어주면,
객체 안에서 키 값이 중복된 프로퍼티는 마지막에 선언된 프로퍼티를 사용하기때문에 저렇게 넣어줘도 상관없는것이다.
다른 보드끼리 이동
보드끼리 이동 문제 없으나
모든걸 다 옮겼을 때
받는 역할인 div , 즉 receiver가 매우 영역이 좁아져있어서 최대한 제목까지 올려야만 이동이 된다.
댓글에 있는
const onDragEnd = ({ draggableId, destination, source }: DropResult) => {
if (!destination) return;
setToDos((allBoards) => {
const copyToDos: IToDoState = {};
Object.keys(allBoards).forEach((toDosKey) => {
copyToDos[toDosKey] = [...allBoards[toDosKey]];
});
copyToDos[source.droppableId].splice(source.index, 1);
copyToDos[destination.droppableId].splice(
destination.index,
0,
draggableId
);
return copyToDos;
});
};
같은 보드안에서 이동, 다른 보드끼리 이동 한번에 처리가능합니다!
droppable 또 다른 인자 snapshot
인자 snapshot 오른쪽 마우스 눌러 type설명을 보면어떤 기능들이 있는지 알 수 있다.
Area는 단순 styled된 div이기때문에 prop인식하지 못해서 styled에 type 설명해주기
interface IAreaProps { //두 개라 길어져서 interface로 만듬
isDraggingOver: boolean;
isDraggingFromThis: boolean;
}
const Area = styled.div<IAreaProps>`
background-color: ${(prop) =>
prop.isDraggingOver
? "pink"
: prop.isDraggingFromThis
? "red"
: "blue"};
flex-grow: 1;
transition: background-color 0.3s ease-in-out;
`;
function Board({ toDos, boardId }: IBoardProps) {
return (
<Wrapper>
<Title>{boardId}</Title>
<Droppable droppableId={boardId}>
{(magic, snapshot) => (
<Area
isDraggingOver={snapshot.isDraggingOver}
isDraggingFromThis={Boolean( //편의를 위해 이름을 바꿈
snapshot.draggingFromThisWith
)}
ref={magic.innerRef}
{...magic.droppableProps}
>
스타일 변경
https://flatuicolors.com/palette/us
Flat UI Colors 2 - 14 Color Palettes, 280 colors 🎨
280 handpicked colors ready for COPY & PASTE
flatuicolors.com
https://github.com/UHyun-K/trello-clone/commit/475621c9de6f3043976b5a5b0ba4ee485fda8e8c
style · UHyun-K/trello-clone@475621c
Show file tree Hide file tree Showing 2 changed files with 18 additions and 10 deletions.
github.com
'코딩 > Today I Learn' 카테고리의 다른 글
React animaiton #framer-motion (0) | 2022.09.26 |
---|---|
React Js Master #10 Ref,CrossBoardMovement (0) | 2022.08.03 |
React Js Master #8 (0) | 2022.05.31 |
React Js Master #7 React-hook-form ,register,watch, ,handleSubmit, formState (0) | 2022.05.11 |
React Js Master #6 state management Recoil (0) | 2022.05.09 |