react.js 필기

배코딩·2023년 7월 4일
0

note

목록 보기
63/114

렌더링

기본적으로 변화 없는 부분들은 리렌더링 하지 않음

단 컴포넌트의 상태가 변하면 그 컴포넌트의 내부를 싹 다 리렌더링함.

만약 부모 컴포넌트 상태가 변했을 때, 만약 자식 컴포넌트가 변화가 없을 때는 리렌더링 되는걸 막아서 속도 이슈를 해결하고자 한다면,

const 컴포넌트변수명 = React.memo(자식 컴포넌트)

이렇게 memo를 활용해서 변화가 없을 때 리렌더링을 막을 수 있음.

물론 부모 컴포넌트의 상태 변화에 따라 자식 컴포넌트에도 특정 변화가 발생한다면 그 때는 렌더링을 해주게 됨


cleanup function

useEffect의 첫 번째 인자로 넣은 함수에 대해, 그 함수 안에 return문에 함수를 적어두면, useEffect가 포함된 해당 컴포넌트가 파괴될 때 적어뒀던 그 함수가 실행되면서 파괴됨


styled components

상위 컴포넌트의 props

손자 컴포넌트는 조상 컴포넌트의 props를 사용할 수 있다.


typescript

만약 타입스크립트 create-react-app에서 라이브러리를 받았는데 js 기반이라면, 타입스크립트 설명 파일을 따로 받아줘야 함. 만약 해당 패키지에 대한 타입스크립트 설명 파일이 깃헙 레포에 없을 수도 있는데, 없으면 아래 명령어가 실행이 안될거임. 어쩔수 없지 머

npm i --save-dev @types/패키지이름

깃헙의 DefinitelyTyped 레포에서 찾아볼 수 있는데 대다수를 숨겨두고 천 개만 보여주기 때문에, 직접 레포 드가서 찾는건 비추. 걍 명령어 한 줄 때려보자


typescript interface 쉽게 쓰기

보통 API interface 정의 자동으로 해주는게 있긴 하지만, 강의에서는 손수 써보자고 하면서 쉽게 쓰는 방법 알려줌

코드에서 state 객체 콘솔 로그한다음에, 콘솔 창에서 우클릭 후 "전역 변수로 object 저장" 한다음, temp1로 저장될텐데 Object.keys(temp1).join() 출력 값 복사해서 ide에 복붙한 다음에, 콤마 드래그한 후 윈도우의 경우 ctrl + d 를 누르면 다음 콤마를 자동 다중 선택함. 이런 식으로 계속 다중 커서 해준다음에 모든 콤마가 드래그됐으면, del 누르고 엔터 누르면 싹 정리됨

키값들 모두 드래그 후, shift + alt + i 누르면 모든 라인 커서를 가장 우측으로 옮기고(다중 커서),

value의 경우에는 Object.values(temp1).map((v)=>typeof v).join() 요걸로 타입들 다 구해준 후 똑같이 코드 에디터에 기입하면 됨

다만 이 방법으로 하면 Array도 Object로 타입 체킹이 되버려서, 이 키 값들에 대해서만 따로 인터페이스 작성 후 넣어줘야하는 단점이 있긴 함


react-query

route를 전환해도 기존에 불러왔던 API 데이터를 캐시에 저장해둠. 따라서 다른 페이지 갔다가 다시 되돌아와도 다시 fetching을 안해도 됨. 데이터가 남아있음


apexchart

JS 라이브러리임. 여러 가지 차트로 데이터를 시각화해줌. 리액트에서도 사용 가능. props들은 공식 문서 참고하자


interface

fetching해서 받아올 데이터가 object의 array라면, object에 대한 interface(IData)를 선언 후, hook의 꺾쇠안에 IData[] 요런 형태로 넣어주면 됨.


nullish 병합 연산자

a ?? b

: a가 null도 아니고 undefined도 아니면 a. 그 외엔 b


react-query 에서 refetchInterval

브라우저가 포커싱된 상태에서만 적용. 백그라운드에서 계속 refetching하려면 refetchIntervalInBackground를 사용하자.


react-helmet

컴포넌트임. 여기서 뭘 렌더링하던 모두 문서의 head로 감.

이걸로 route마다 그에 맞게 웹 제목 바꿀 수도 있음


ReactQueryDevtools

API fetching해서 받아 캐시에 저장해놓은 데이터를 조회해볼 수 있음


publishing (깃헙 웹 페이지 띄우기)

  1. BrowserRouter props에

    basename={process.env.PUBLIC_URL}

    추가하기

  2. 깃헙 레포에 프젝 올리기

  3. npm i gh-pages

  4. package.json 수정

 "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "deploy": "gh-pages -d build",
    "predeploy": "npm run build"
  },
 "homepage": "https://깃헙닉넴.github.io/레포이름"
  1. npm run build

  2. npm run deploy


recoil vs redux

둘 다 상태 관리 라이브러리이다.

recoil은 직관적이고 코드가 적고, 대신에 devtool이 콘솔에서 봐야돼서 디버깅할 때 좀 불편하고, redux는 devtool이 잘 돼있어서 디버깅하기 좋은데 뭐 하나 수정하면 보일러 플레이트 코드를 적어야할게 많아서 코드 양이 많다.

대규모 상태를 관리해야하면 redux, 그 외의 간단한 프로젝트에는 recoil을 사용하자


onBlur

onClick으로 진입 후, 다시 밖으로 포커싱이 이동되면 이게 onBlur 이벤트임


undefined ?

변수명에 ?를 붙이면, 예를 들어 errors?.extraError?.message면, errors가 undefined면 그 뒤에는 실행하지 않고, errors가 있어도 extraError가 undefined면 그 뒤 message는 실행하지 않음.


interface string 대신 지정 문자열

interface IPrac {
	category: "A" | "B" | "C";
}

코드 분리

일단 지저분하더라도 작동 가능하게 코드를 짜고, 이후에 코드 리팩토링하는걸 추천


props 작성 형태

{text: "asd"} 대신에, 만약 변수나 매개변수로 text가 이미 존재한다면(ex text="asd")
const 변수 = {text} 이렇게 하면, text 키에 "asd"가 들어간 형태로 적용됨


selector

파생된 상태를 만듦

기존의 atom으로부터, 정제한 새로운 형태의 state를 리턴할 수 있음

이 새로운 파생 상태도 기존의 atom의 상태와 연결되어 같이 갱신됨

물론 selector에서 리턴하는 행위는 원본을 변경시키지 않음


type (복붙 안하게 해주는 편한 문법)

type 변수명 = 값;


enum (열거)

enum 이름 {
	문자열,
    문자열,
}

이름.문자열 형태로 사용

interface로도 사용 가능

이 때, 실제 리턴값은 인덱스 넘버임.

만약 스트링 그대로 쓰고싶다면 + " " 를 해주자. 아니면 enum에서 문자열 = 문자열 로 선언을 해줘버려도됨


selecter : set

selector의 인자로 넘기는 객체의 set 프로퍼티에는 함수가 들어간다. 이 함수의 인자로 opt 객체가 기본 제공되는데 여기서 set을 활용하면 다른 atom에 들어있는 값을 할당할 수 있다.

set으로 atom의 값을 변경한 직후, 다시 get에서 리턴된 값이 selector에 저장된다.


드래그 앤 드랍 라이브러리

npm i react-beautiful-dnd

react 18에서는 strict를 끄고 해야 정상 작동함


DragDropContext > Droppable > Draggable

DragDropContext에는 onDragEnd prop을, Droppable과 Draggable 컴포넌트에는 draggableId와 index를 props로 주고, children에는 리액트 요소(태그)가 직접적으로 들어가면 안되고, 익명 함수 형태로 작성 후 매개변수로 magic(provided)을 넘겨받아, 여기에 담긴 props들을 리액트 요소에 prop으로 넣어주면 된다.

특정 요소를 드래그 시작 클릭 부분으로 설정하려면, magic의 dragHandleProps를 그 요소 prop에다가 넣어주면 된다.

Draggable의 key와 draggableId는 값이 같아야 함(그래야 버그 발생 여지 없음)


magic.placeholder : Droppable 내의 영역 태그 내부에서 코드가 끝나기 직전 부분에 {magic.placeholder}를 추가해주면, 영역 내 요소를 드래그해서 밖을 빼내도 영역의 크기가 자동으로 줄어들거나 하지 않고 고정됨


타입 명시

라이브러리쓸 때 함수 인자로 들어오게 될 값들에 대한 인터페이스가 뭘지 모르겠다면, 우클릭이나 컨트롤 클릭으로 type definition 들어가서 살펴보자


arr.splice(index, deleteCount?, item);

arr.splice(index, deleteCount)

arr 원본에서 index 자리 원소로부터 deleteCount개만큼 연속적으로 원소를 지움. 원본이 변경되며, 이 함수 자체의 리턴값은 지운 것들로 구성된 배열임.


arr.splice(index, 0, item);

index 자리에 item을 추가함


react memo (최적화에 유용)

해당 컴포넌트는 "prop이 바뀌지 않는 한" 리렌더링하지말라고 명시하는 것

기준이 prop의 변화라는 점 주의하자!

export default React.memo(컴포넌트를 분리해놨다면 그 파일명);

이런 식으로 써주면 됨


인터페이스 확장성

[key: string]: string[]

요렇게 하면, 객체의 프로퍼티가 string이고, value가 string[]이라고 알려주는거임


react-beautiful-dnd props

Droppable과 Draggable 컴포넌트 모두 children 컴포넌트가 magic과 snapshot을 받을 수 있다. 뭔 이름으로 받든 상관은 없다. magic은 드래그 앤 드랍에 필요한 props 들을 제공해주고, snapshot에는 드래그와 관련된 정보가 담겨있다. (드래그 시작 위치, 드래그 중 특정 컴포넌트 위에 위치하는 이벤트 감지 등). 스타일링에 써먹기 좋음


useRef

const inputRef = useRef<HTMLInputElement>(null);
const onClick = () => {
    inputRef.current?.focus();
    setTimeout(() => {
      inputRef.current?.blur();
    }, 5000);
};

<input ref={inputRef} placeholder="grab me" />
<button onClick={onClick}>click me</button>

HTML 요소에 바로 접근하여 관련 메소드 등을 활용할 수 있다.

useRef hook을 사용하여 inputRef에 ref를 담아둔다.

react 요소의 ref prop에 inputRef를 넣어두면, 이 ref에 HTML 요소가 담겨있어 리액트에서 접근할 수 있게 된다. 물론 그 요소의 메소드들도 모두 활용가능해진다.

예로 버튼을 만들어서 이 버튼을 클릭했을 때, inputRef.current로 현재 ref가 참조하고 있는 HTML 요소이고, 이 것이 본래 가지고 있는 메소드들을 모두 활용할 수 있다.


라이브러리 버전 호환 안될 때

예를 들어 framer motion이 버전 5고 create-react-app이 버전 4일 때, framer motion에서 사용하는 ecmascript modules를 create-react-app에서 읽지 못한다고 하자.

이런 식으로 어떤 라이브러리를 사용하려고 하는데 create-react-app에서 호환이 잘 안된다면, CRACO를 사용해서 configuration을 overriding 해주면 됨. CRACO 깃헙 페이지를 참고하자


framer motion

framer-motion

여러 animate 용이하게 써먹는 라이브러리

JSX 태그에 바로 적용 못하고, div 대신 motion.div 이런 식으로 써야함. 물론 motion에서 지원하는 태그들만 가능


motion.태그명 스타일링

이미 div 스타일링해둔게 있다면, 예를 들어 그게 Box 스타일 컴포넌트라 치면

const Box = styled(motion.div) ~~~

요런 식으로 하면 됨


prop

initial, animate 등 여러 prop이 있고, 이 안에는 객체를 넘겨주는데 그 객체에는 normal css를 그대로 활용해서 작성하면 됨. 물론 framer-motion에서 자체적으로 제공하는 프로퍼티도 있긴 함


transition에서 type: spring

탄성을 줌. 이와 더불어 damping, stiffness 등의 프로퍼티를 사용하여, 현실 세계의 물리 법칙을 적용시켜줄 수 있음. 이런 내용들의 자세한 부분은 framer docs 참고


variants

const myVars = {
  start: { scale: 0 },
  end: { scale: 1, rotateZ: 360, transition: { type: "spring", delay: 0.5 } },
};

function App() {
  return (
    <Wrapper>
      <Box variants={myVars} initial="start" animate="end" />
    </Wrapper>
  );
}

이런 식으로 props들을 따로 myVars 객체에 선언해두고, 이걸 컴포넌트의 variants prop으로 넘겨준 뒤, 다른 initial이나 animate 등의 prop의 값으로, variants 내의 프로퍼티명과 맞춰주면 자동으로 매핑돼서 들어감


variants 상속

부모 컴포넌트에서 설정한 variants와 props는 자식 컴포넌트에게 자동 상속됨


variants 타입

framer-motion에서 Variants를 import할 수 있고, 이건 인터페이스로 활용할 수 있음. 즉 자동완성에 용이함


자식 컴포넌트 제어

transition에 delayChildren, staggerChildren 등 framer-motion에서 제공하는 프로퍼티가 있음. 잘 활용하자


animate 바깥에서의 prop

animate 내부가 아니라, 그 외 예를 들어 whileDrag prop을 작성한다고 치면, 여기에 backgroundColor에 "blue" 처럼 string으로 넣으면 애니메이션이 적용이 안됨. rgb나 rgba처럼 숫자가 포함된 값을 넣어주면 애니메이션이 자동 적용됨


MotionValue

motionvalue는 state가 아니다. 따라서 변해도 자동 리렌더링되지않음

참고로, motionvalue는 get과 set 함수가 존재한다.

const x = useMotionValue(0);

<Box style={{ x, scale }} drag="x" dragSnapToOrigin />

이런 식으로, Box 컴포넌트를 드래그할 때마다 x 값이 변할텐데, 저렇게 style에서 x: x 로 등록해주면, 컴포넌트의 x값과 motionvalue인 x가 연결되어, 드래그할 때마다 motionvalue도 업데이트됨


useMotionValueEvent

motionvalue의 이벤트를 감지하여 callback 함수를 실행시킬 수 있다.

useMotionValueEvent(x, "change", (v) => {
    console.log(v);
  });

useTransform

motionvalue의 range를 특정 range로 정규화 또는 축약해서 얻어낼 수 있음.

const x = useMotionValue(0);
const potato = useTransform(x, [-400, 0, 400], [2, 1, 0.1]);

return (
    <Wrapper>
      <Box style={{ x }} drag="x" dragSnapToOrigin />
    </Wrapper>
);

useScroll

scroll 위치에 관한 정보를 motionvalue 형태로 받아낼 수 있다.


객체 shortcut

const scale = 1;
<Box style={{ scale }} />

scale: scale 처럼 프로퍼티명과 거기 넣을 변수명이 같다면, scale 한 단어로 축약가능


svg

fontawesome에서도 svg로 받을 수 있고, 그림 파일을 svg로 변환하거나 피그마 컴포넌트로 svg로 export 가능함.

여기에 framer-motion 적용하고 싶으면 svg 태그 내의 path 태그를 motion.path로 바꿔주자.

이 때 path의 fill의 값으로 currentPath를 쓰면, svg 태그(또는 컴포넌트)에 설정된 color로 적용됨

stroke로 테두리도 설정 가능

물론 path의 스타일링을 Svg 컴포넌트를 정의해두고 거기 스타일 컴포넌트 문법 안에 태그 선택자로 path를 지정해서 스타일링하는 것도 가능. 이 방식을 더 추천


pathLength

svg 내의 path의 프로퍼티로 사용가능함.

테두리 선을 그리는걸 0부터 1까지로 했을 때, 이 프로퍼티의 값만큼까지만 테두리를 그려서 표현함. 0은 아예 없고, 1은 완전히 다 그려진 형태


프로퍼티마다 개별로 transition 주기

transition={{
            default: {
              duration: 5,
            },
            fill: { duration: 2, delay: 5 },
          }}

컴포넌트(or 태그)의 prop에 이런 식으로 써주면 property 별로 따로 transition 지정 가능

variants에 쓰면 일괄 적용되버리고, 태그의 prop에서 저렇게 작성해주면 개별 적용 가능함


사라지는 컴포넌트 animate 하기

framer-motion 라이브러리의 AnimatePresence 컴포넌트를 활용하면 됨

조건 1. AnimatePresence 컴포넌트는 항상 visible 이여야함
조건 2. 자식 컴포넌트에 조건식이 있어야 함. {showing ? : null} 요런거

AnimatePresence 내에 들어갈 조건식 내의 컴포넌트의 prop에 exit prop을 넣어주면 됨. 값으로는 당연히 애니메이션 내용이 들어갈테고(style이나 아니면 variants로 지정해둬도 되고), exit은 컴포넌트가 사라질 때 적용될 애니메이션을 넣는 prop임

이 때, 예를 들어 Box를 1~10까지 10개를 생성할 필요 없음. 박스 넘버를 state로 만들어두고, 그걸로 box의 key prop에 state를 넣어주면, 리액트는 key가 변했을 때 기존에 있던 박스가 사라졌다고 간주하고 새로운 key에 해당하는 박스가 새로 생겼다고 알아서 간주해서, 기존걸 없애고 새로운걸 렌더링함. 즉 array map 쓸 필요없이 그냥 컴포넌트 하나만 작성해두고 key에 state만 잘 넣어두면, 무사히 exit 애니메이션과 등장 애니메이션이 있는 슬라이더 구현 가능함.

핵심은 key prop에 각 컴포넌트 고유 식별 값에 해당하는 state를 넣기!


custom

AnimatePresence와 대상으로 삼고자 하는 자식 컴포넌트의 prop에 custom={state변수} 요렇게 넣어주면 됨.

state를 variants에서 활용할 수 있게 됨. 사용법은 프로퍼티 value에 값 말고 함수 형태로 적어넣은 다음, 프로퍼티 value로 사용될 값을 함수 내에서 return하면 됨


이전 컴포넌트와 이후 컴포넌트의 애니메이션들 타이밍 조작

AnimatePresence에 prop으로 mode="wait"을 넣어주면, 이전 컴포넌트가 exit하는걸 다 기다리고 난 후에 새로운 컴포넌트가 enter 한다.

mode의 기본 값은 sync이다. (거의 동시에 진행)

이 경우 next를 하다가 prev 버튼을 바로 눌러주면 애니메이션에 문제가 생기는데, 이는 state의 setter가 비동기이기 때문임. 즉 useEffect로 custom state를 동기적으로 바꾼 후(이 때 값은 객체 형태로 넣자. state에 변화가 없더라도 그 값이 객체면 업데이트가 있는 것으로 간주해주기 때문), 완전히 바뀐 후에 슬라이더와 연관된 state의 setter가 호출되어야 함.


const box = {
  entry: (isBack: boolean) => {
    return {
      x: isBack ? -500 : 500,
      opacity: 0,
      scale: 0,
      transition: { duration: 0.3 },
    };
  },
  center: {
    x: 0,
    opacity: 1,
    scale: 1,
    transition: { duration: 0.3 },
  },
  exit: (isBack: boolean) => {
    return {
      x: isBack ? 500 : -500,
      opacity: 0,
      scale: 0,
      transition: { duration: 0.3 },
    };
  },
};

function App() {
  const [visible, setVisible] = useState(1);
  const [back, setBack] = useState(false);
  const nextPlease = () => {
    setBack(false);
    setVisible((prev) => (prev === 10 ? 10 : prev + 1));
  };
  const prevPlease = () => {
    setBack(true);
    setVisible((prev) => (prev === 1 ? 1 : prev - 1));
  };
  return (
    <Wrapper>
      <AnimatePresence custom={back}>
        <Box
          custom={back}
          variants={box}
          initial="entry"
          animate="center"
          exit="exit"
          key={visible}
        >
          {visible}
        </Box>
      </AnimatePresence>
      <button onClick={nextPlease}>next</button>
      <button onClick={prevPlease}>prev</button>
    </Wrapper>
  );
}

layout prop

외부 요인 등에 의해 컴포넌트의 레이아웃이 변경될 때 애니메이션을 주고 싶다면, prop에 layout이라고 적어주면 끝

function App() {
  const [clicked, setClicked] = useState(false);
  const toggleClicked = () => setClicked((prev) => !prev);
  return (
    <Wrapper onClick={toggleClicked}>
      <Box
        style={{
          justifyContent: clicked ? "center" : "flex-start",
          alignItems: clicked ? "center" : "flex-start",
        }}
      >
        <Circle layout />
      </Box>
    </Wrapper>
  );
}

Shared layout animation

const Circle = styled(motion.div)`
  width: 100px;
  height: 100px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
  background-color: #00a5ff;
`;

function App() {
  const [clicked, setClicked] = useState(false);
  const toggleClicked = () => setClicked((prev) => !prev);
  return (
    <Wrapper onClick={toggleClicked}>
      <Box>
        {!clicked ? (
          <Circle layoutId="circle" style={{ borderRadius: 50 }} />
        ) : null}
      </Box>
      <Box>
        {clicked ? (
          <Circle layoutId="circle" style={{ borderRadius: 0, scale: 2 }} />
        ) : null}
      </Box>
    </Wrapper>
  );
}

두 컴포넌트가 있고, 둘 다 prop에 layoutId를 같은 값으로 지정해주면, 이 둘은 서로 달리 존재하는 별개의 컴포넌트이지만 framer-motion에 의해 UI 상에서는 같은 컴포넌트로 인식된다. 그래서 위 코드 예제에서 두 컴포넌트는 상태 값에 의해 둘 중 하나만 화면에 보여지는데, 상태가 변하면서 하나가 꺼지고 하나가 생겨날 때 마치 하나의 컴포넌트가 새로운 위치로 이동하는 것처럼 애니메이션을 준다.


framer-motion : variants

설정할 때, 프로퍼티 값에 배열을 넣으면 배열 원소들을 순서대로 다 애니메이팅 해준다.


Router (v5 기준)

path="/" 인 Route는 비교할 때 항상 true를 반환함(모든 경로는 /로 시작하니까)

그래서 home route는 마지막에 배치하자


Router : useRouteMatch("/경로")

현재 렌더링중인 라우터가 인자로 넣은 경로와 일치하는지를 boolean으로 리턴해주는 hook


framer-motion : transform-origin

transform-origin: right center;

이런 식으로 씀. 애니메이션 변형이 시작되는 부분을 지정할 수 있음


framer-motion : useAnimation

motion.태그 컴포넌트에 animate prop을 작성해서 애니메이션을 적용하는게 아닌, 특정 코드를 통해 해당 컴포넌트에 애니메이션을 걸고 싶을 때는 useAnimation hook을 사용하면 됨.

useAnimation 객체를 inputAnimation 변수에 담아뒀다고 치자.

컴포넌트의 animate prop에 inputAnimation 변수를 넘기고, 임의의 함수를 정의한 후 거기에 inputAnimation을 활용한 애니메이션 트리거 코드를 작성해두면 된다.

inputAnimation.start({scaleX: 0} 이런 식으로

주로 여러 애니메이션을 동시에 실행시키기 싶을 때 유용하게 쓰이는 hook임.


참고로, variants 내의 프로퍼티명은 useAnimation 객체의 메소드들(start 등)에서도 똑같이 사용가능하다.


react-query key

useQuery의 인자로 key가 들어가는데, 쿼리의 고유 식별자이다. 중복되는 키 값을 써야한다면, 리스트 형태로 다중 키를 보내주면 된다.

두 번째 인자는 fetcher 함수이다.

리턴값으로 객체를 받고, 거기에는 data 프로퍼티와 isLoading 프로퍼티 등이 있다.


CSS : background-image

여러 개 지정 가능함. 이를 응용해서 하나는 0.5 투명도의 검은 색상 두 개의 linear-gradient와 그림을 같이 넣으면 배경 그림을 좀 더 어둡게 표현가능함

이런 식으로 linear-gradient를 활용하면 배경을 부분적으로 어둡거나 밝게 표현할 수도 있고 다른 색상을 희미하게 덧씌울 수도 있음

background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1)),
    url(${(props) => props.$bgPhoto});

AnimatePresence : onExitComplete

AnimatePresence의 onExitComplete에, exit 애니메이션이 끝난 후 실행할 함수를 넣어둘 수 있다.

이는 슬라이더에서 넘기는 도중에 다시 넘기도록 지시해서 슬라이더가 겹쳐져서 막 넘어가버리는 현상을 방지할 때 써먹을 수 있는 로직이다.

예를 들어 index state를 생성해두고, AnimatePresence 내의 Row의 key가 index라서 자동으로 파괴와 생성을 구현했을 때, 다음이나 이전 버튼 눌러서 index state를 증감시켰을 때, leaving state가 true인지 false인지에 따라 index의 증감을 막아두는 조건문을 작성해두고, onExitComplete에서 leaving을 토글하는 설정을 해두는 식으로 방지할 수 있다.


AnimatePresence : initial

motion 태그가 아닌 AnimatePresence 컴포넌트의 prop 에서의 initial 말하는 거임.

이걸 false로 설정해두면, 최초 route 페이지 렌더링될 때 initial에서부터 시작하는걸 방지할 수 있음. 즉 처음 시작할 때만 animate의 결과 상태로 렌더링돼있음.


react-router-dom : useHistory

Link 말고도, 다른 trigger를 통해 링크를 바꿀 수 있게 해주는 훅


react-router-dom : route path array

Route 컴포넌트의 path prop에 배열 형태로 경로를 넣어줄 수 있다. 해당 경로들에 대해 모두 같은 Route를 렌더링한다.


javascript : URLSearchParams("?keyword=blabla®ion=kr");

주소에 query argument가 포함되어 있을 때, 이걸 쉽게 파싱해서 얻을 수 있게 해주는 자바스크립트 자체 함수이다.

new 키워드로 객체를 생성하고, get 메소드를 get("keyword") 이런 식으로 호출하면 값("blabla")을 얻을 수 있다.

profile
PS, 풀스택, 앱 개발, 각종 프로젝트 내용 정리 (https://github.com/minsu-cnu)

0개의 댓글