react-kanban 미리스터디

찜와와·2023년 7월 14일

library

목록 보기
1/3

사용하는 오픈소스:
링크텍스트

=> 얘를 사용하려 했으나 typesript 의 사용으로 포기함

해결책: 다른 오픈소스를 찾았다

rfc + [tab] 을 누르면 자동완성 코드가 뜬다

import React from 'react'
export default function KanbanBoard(){
	return(
		<div> KanbanBoard</div>
	)
}

에러 1) node-modules/node-sass: Command failed

node-sass 모듈과 node 버전 차이로 인한 오류
원인: package.json에 설정된 node-sass버전이 로컬에 설치된 node 버전과 맞지 않음

내 로컬에 설치된 node버전은 v18이지만 node-sass버전은 v8
해결방법: node-sass를 최신버전으로 로컬에 재설치

yarn add node-sass

에러2) digital envelope routines

원인: node.js 버전을 최신 버전으로 변경한 것
해결책: LTS버전으로 재다운/다운그레이드

node -v
//node.js버전확인
sudo npm cache clean --force
//캐시 삭제
sudo npm install -g n
//n을 사용하면 node.js 버전을 쉽고 간편하게 관리가능
n latest
//최신 버전 설치
n lts
//안정 버전 설치

-> 해결안됨
링크텍스트


위 방법으로 yarn start 를 재실행하여 성공함

task 삭제,추가 까지는 가능

아래 오픈소스 이용
링크텍스트

drag&drop 기능 추가

react styled component 설치

npm i react-beautiful-dnd ant styled-components
재사용가능한 스타일 컴포넌트를 제공함

npm run dev
프로젝트 실행

scroll 기능은 가능하지만 scroll바가 안보이게끔 실행


scroll.css 파일에 스크롤바가 display: none; 이 되게끔 명령
kanbanboard.jsx 에서 import

리액트 훅

리액트 클래스형 컴포넌트에서 이용하던 코드를 작성할 필요없이 함수형 컴포넌트에서 다양한 기능을 사용할 수 있게 만들어준 라이브러리

JSONPlaceholder

이게 뭐야?
백엔트 서버가 없을 때 임시로 가상데이터를 만들어 api 테스트를 가능하게끔 하는 것
방법?
JSONPlaceholder url을 통해 리소스를 불러올 수 있다

useState 사용법

state란?
컴포넌트가 가질 수 있는 상태
예. '시간'컴포넌트 -> state로 현재 시간
[import]
reactHook의 useState는 컴포넌트의 state를 간편하게 생성하고 업데이트를 시킬 수 있게 해주는 도구를 제공한다

import {useState} from 'react';

[변수 선언]
state의 생성과 동시에 가지는 초기값을 useState함수의 인자로 넣으면 state와 setState라는 두가지 요소를 배열 형태로 반환한다.

const [state, setState] = useState(초기값);

[변수 재선언]
setState함수를 부르면 state값을 변경할 수 있다.

setState(1);
//state의 값을 1로 변경한다

setState함수로 state의 값을 변경할 수 있다.
(이때 해당 컴포넌트는 다시 렌더링되어 state가 변경될 때마다 업데이트됨)

react div 스크롤 시 fix하기

SPA :: Single Page Application
서버에서 제공하는 페이지는 하나지만 브라우저의 주소상태에 따라 다양한 화면을 보여준다
(라우팅:: 다른 주소에 다른 화면을 보여주는 것
리액트 라우터 종류:: 1) react-router, 2) reach-router, 3) next.js)

import "./styles.css";
import { useRef, useState, useEffect } from "react" ;
//SPA리액트에서 특정 엘리멘트를 사용하기 위해 useRef를 사용

export default function App() {
	const boxRef = useRef(null);
    //box라는 특정 앨리멘트선택 useRef
    const [Scrolly, setScrolly] = useState(0);
    //scrolly의 초기값은 0이고 setScrolly가 함수
    const [ScrollActive, setScrollActive] = useState(false);
    //scrollActive의 초기값은 false이고 setScrollActive가 함수 
    
    function logit(){
    	setScrolly(boxRef.current.scrollTop);
        //boxRef의 현재 스크롤위치 반환
        if(boxRef.cureent.scrollTop > 30) {
        	setScrollActive(true);
            // 스크롤 위치가 30이상이면 setScrollActive함수 활성화
        }else{
        	setScrollActive(false);
        }
    }
    
    useEffect (() => {
    	function watchScroll() {
        	boxRef.current.addEventListener("scroll", logit);
            //logit에 따라 스크롤이벤트
        }
        watchScroll();
        return () => {
        	boxRef.current.removeEventListenr("scroll", logit);
        }; 
        //현 이벤트 삭제
    });
    
    return (
    	<div className = "App">
        	<div className = "box">
            	<div className = {ScrollActive ? "smallBox fixed" : "smallBox"}>
                	{ScrollActive ? "I am fixed!" : "I will be fixed"}
                </div>
            	<div className = "boxInner" ref = {boxRef}>
            		{" "}
                	{/* boxRef 설정 */}
                	document blablablablaksjfkflksajfkjfkj
                	afkdsfjkljfksfjlkajflkajfkdjlf
               	 	ajdksfjslkfj
                	asfkdjfkasjdfkjfdsfkasjfl
               </div>
            </div>
        </div>
    )
    
    
}

DragNDrop 간단 소개

목적:: 총 3개의 객체에 대해 action

DragDropContext :: 전체 어플리케이션을 감싸는 wrapper
Droppable :: drop할 수 있는 영역 (draggable을 감싸는 wrapper)
Draggable :: 주체, Drag가 가능한 컴포넌트를 감싸는 wrapper

onDragStart : drag가 시작될때 호출
onDragUpdate : 새로운 변화가 생길때 (예. drag진행중 새로운 위치로 이동)
onDragEnd : drag가 끝날때 호출**

백엔드에 drag and drop 할때마다 put 요청

axios요청

axios install을 하던 중 incompatible module 발생

원인 : 패키지버전과 노드 모듈 버전이 달라서 생기는 에러
해결책 : yarn global add axios --ingnore-engines
"--ignore-engines" 로 마무리

snapshot

특정 시간에 데이터 저장 장치의 상태를 별도의 파일이나 이미지로 저장하는 기술로 스냅샷 기능을 이용하여 데이터를 저장하면 유실된 데이터 복원과 일정 시점의 상태로 데이터를 복원할 수 있다.

해야하는 부분

실행시킬때 npm run dev
todo, done 부분
=> main페이지 자체에서 drag, drop 가능하게끔
애니메이션 추가 (부드럽게 drop할 수 있게끔)

참고글 1
참고글 2

미디어/파일 dropzone 참고글
dropzone참고글 3

react-beautiful-dnd 라이브러리 설치

각 task에서 scroll을 할 때 네비게이션 바가 보이지 않게끔 구현

제출기한, 과제내용, 강의명을 id값으로 넘김

snapshot 인수를 이용한 dragNdrop 액션효과 추가

column 이 2개(todo,done)에서 3개(todo,doing,done)인 경우

부연설명
DropNDrag참고자료

droppable

drop이 가능한 영역으로 이 영역에서 item을 drop할 경우에 DragDropContext가 바인딩 된 onDragEnd={...} 함수가 동작하며 최종적인 Drag and Drop 동작에 대한 dom을 그려주기에 필수적으로 영역을 지정해줘야 한다

Droppable은 droppableId를 필수적으로 입력해야 드롭될 영역의 고유 ID를 의미한다.
아래 예시에서는 Array.map()메서드를 사용햐여 각각의 고유한 영역을 지정했고 각각의 영역이 받는 처음 값을 droppableID로 지정했다. 이 값은 string 형태로 변환하여 넣어주어야 한다.
providedprovided.innerRef를 참조하여 동작을 실행하는 매개변수이기에 반드시 들어가야하고
snapshot은 동작시 dom 이벤트에 대해 적용될 style 참조를 의미한다 (선택적 항목)

예시 코드

import { Droppable } from "react-beautiful-dnd";

<DragDropContext
        onDragEnd={props.handleDragEnd}
        onDragStart={props.handleDragStart}
      >
        {props.categoryName?.map((el: string[], index: number) => (
          <Droppable droppableId={el[0]} key={index}> 
            {(provided, snapshot) => (
              <div ref={provided.innerRef} {...provided.droppableProps}>
                <ExperienceSMAFDetail
                  key={index}
                  el={el}
                  index={index}
                  scheduleArray={props.scheduleArray}
                />
                {provided.placeholder}
              </div>
            )}
          </Droppable>
        ))}
        <S.AddcolumnBtn>
          항목추가
          <S.AddCoulumnIcon
            onClick={props.AddColumn}
            src="/detailPage/addcolumn.png"
          ></S.AddCoulumnIcon>
        </S.AddcolumnBtn>
      </DragDropContext>

draggable

Draggable은 Drag가 일어나는 요소들로 Droppable 영역안에서 움직이는 요소들을 정해준다.
Drag 이벤트가 시작되면 DragDropContext 가 바인딩 된 onDragStart={...}가 동작한다.
draggableID를 필수적으로 받아와야 하는데 Droppable영역에서는 DND가 일어날 영역의 고유값을 입력해주었다면 Draggable에서는 움직일 요소들이 가지는 고유값을 입력해주어야 한다.
Draggable 역시 provided 와 snapshot을 제공하며
providedprovided.innerRef 를 참조하여 동작을 실행하는 매개변수이기에 반드시 들어가야하는 사항이며
snapshot은 동작시 dom 이벤트에 대하여 적용될 style 참조를 의미한다.(선택적 항목)

import { Draggable } from "react-beautiful-dnd";

{props.scheduleArray?.[props.categoryIndex]?.map(
            (el: string, index: number) => (
              <Draggable key={el} index={index} draggableId={el}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.dragHandleProps}
                    {...provided.draggableProps}
                  >
                    <ExperiencePlanCard
                      key={index}
                      el={el}
                      index={index}
                      number={index + 1}
                      categoryNum={props.categoryIndex + 1}
                    />
                  </div>
                )}
              </Draggable>
            )
          )}

column이 3개인 경우 (단, 미리 주어진 task list)

1) source != dest
sourcecolumn 정의 / destcolumn 정의 / sourceitems 정의 / destitems 정의 / removed 정의
removed: sourceitem에서 source.index에 해당하는 원소를 의미함
destitems.splice: dest.index에 해당하는 원소로 removed 추가
setcolumns: ...columns, source.droppable, dest.droppable

2) source == dest
column 정의/ coppieditems 정의
removed: copieditem에서 source.index에 해당하는 원소를 의미함
setcolumn: ...columns, source.droppable

column이 2개인 경우 (현재 사용하고 있는 open source)

1) source == dest
return

2) source.id == 2 (<= 근원지가 done인 경우)
setDone(removeItemByID(draggable,done))
=> 위에서 목적지가 이미 dest와 다름을 안다.
: done 배열에서 draggableID를 제거한 배열을 done으로 설정함
2-1) source.id != 2 (<= 근원지가 todo 인 경우)
setDone(removeItemByID(draggable,todo))
=> 마찬가지로 위에서 이미 근원지와 목적지가 다른 값을 알고 있다.
: todo 배열에서 draggableID를 제거한 배열을 todo로 설정함

task: todo와 done을 합친 배열중에서 draggableId한 값들

3) dest.id ==2 (<= 목적지가 done인 경우)

setDone([{ ...task, completed: !task.completed }, ...done]);

:Done 배열에 ...task에 해당하는 값과, complete(?) 값과 ...그 전의 done 값

3-1) dest.id != 2 (<= 근원지가 todo 인 경우)

setTodo([{...task, completed: !task.completed }, ...todo]);

:Todo 배열에 ...task에 해당하는 값과, complete(?) 값과 ... 그 전의 done 값

0개의 댓글