TIL | [React]

noopy·2021년 11월 9일
1

TIL

목록 보기
19/21
post-custom-banner

리액트 첫 시작!
원래는 Vue 발만 담궜다가 빼기 싫어서 깊게 공부하려고 했는데,
최종 프로젝트에서 Vue로 진행할 수 없을 것도 같아 React도 공부해보려고 한다!
아자아자자자자 👊 다 뿌셔버료

hooks

useReducer

상태 업데이트.

  • ⭐️action⭐️이란 객체를 기반으로 상태를 업데이트.
  • 상태 업데이트 로직을 컴포넌트 밖으로 분리 가능.
    (다른 파일에 작성 후 불러와서 사용도 가능)
  • reducer: 상태를 업데이트하는 함수

  • 컴포넌트 내부에서 불러오는 법

    dispatch: action을 발생시킴.

👾 useState VS useReducer

간단한 거면 useState, 복잡한거면 useReducer

useEffect

1. 무언가 변화가 있을 때 감지(Vue의 watch)

useEffect(() => {}, [dependency])

dependency에 감시할 대상을 넣음.

2. 라이프 사이클

  • dependency가 비었을 경우
    • mounted 될 때 실행
    • 전역으로 등록할 이벤트를 등록할 때도 사용
  • 클리너 함수 return () => {}
    • 컴포넌트가 제거될 때 사용
      • 컴포넌트가 제거될 때 등록한 전역 이벤트도 제거하기

useEffect dependency

dependency에 꼭 넣을 값들

  • 감시할 대상
  • props로 받아온 값
  • useState 값을 참조할 때
  • 함수를 사용할 때

useRef

const 이름 = useRef()

// 사용할 때
이름.current

1. DOM에 직접 접근할 때(Vue의 ref)

  • 컴포넌트의 depth가 깊어져도 useRef로 접근 가능 👍

React.forwardRef((props, ref) => {})

첫번째 인자론 전달받을 props, 두번째 인자론 ref를 받음

import React from 'react';
const Input = React.forwardRef((props, ref) => {
  return (
    <>
      input: <input ref={ref}/>
   </>
  )
})

export default Input;
<Input ref={inputRef} />

바깥에서 ref로 inputRef를 전달하면 자식 컴포넌트에서 두번째 인자로 받은 ref로 자동으로 들어감.

2. 지역변수로 사용될 때, 컴포넌트가 리렌더링될 때마다 기억될 수 있는 값으로 사용할 때(Vue의 computed)

useState VS useRef

useStateuseRef
값이 바뀌면 리렌더링값이 바뀌어도 리렌더링하지 않음

useMemo

  • 함수 컴포넌트가 리렌더링될 때
      1. 자신의 상태가 변경될 때
      1. 부모 컴포넌트로부터 받는 prop이 변경될 때
      1. 부모 컴포넌트의 상태가 변경될 때

부모로부터 두개의 prop를 받는 함수가 있을 때, 함수의 연산값은 변하지 않더라도 다른 prop가 변경되어서 전체가 리렌더링되는 것을 볼 수 있다.

useMemo는 특정 상태가 변경됐을 때만 함수를 실행할 건지를 설정할 수 있다.

  useMemo(() => function, [input])
// 어떠한 input이 변경됐을 때 function을 호출할 건지 설정

React.memo

useMemo에서 3번을 해결하기 나온 훅!
즉, 자식 컴포넌트의 상태가 변경되지 않으면 리렌더링 하지 않도록 설정할 수 있다.
(부모의 상태 변화가 자식 컴포에 영향을 주지 않도록)

import React from 'react';
// 함수를 React.memo로 감싸주기
const Component = React.memo(() => {})

useCallback

함수 컴포넌트는 리렌더링될 때마다 새로 정의된다.
특정한 상태가 바뀌었을 때만 함수를 호출할 때 사용하는 useMemo처럼,
useCallback은 함수를 사용했을 때 deps에 넣은 값들이 바뀌지 않으면 이전 함수를 재사용해서 컴포넌트 렌더링을 최소화한다.


세 CheckBox 컴포넌트는 부모 컴포넌트로부터 prop를 받아 상태를 변경한다.
React.memo를 사용해서 자식 컴포넌트의 상태가 변경되지 않으면 리렌더링되지 않게 설정했으나, 한 컴포넌트의 상태가 변경이 되면 리렌더링되므로 함수가 재정의돼서 새로 메모리에 함수가 할당되기 때문이다.

const function = useCallback(() => {}, [dependency])

Custom Hook

자주 사용하는 상태로직을 사용자 정의 훅으로 만들어 재사용성을 높임.

Context API

Prop Drilling: 컴포넌트의 depth가 깊어질 때 부모와 자식, 조상과 자손간의 prop을 계속 넘겨줘야 하는 현상

Prop Drilling을 해결하는 도구들

  • Redux
  • Recoil
  • Mobx
  • Context API

데이터를 보내는 주체: Context Provider
데이터를 받는 주체: Context Consumer

// Provider
// 1. context 만들기
const PostContext = createContext

// 2. consumer가 사용할 수 있도록 함수 등록
export const usePostContext = () => useContext(PostContext)

return (
  <PostContext.Provider value={{ 자식에게 줄 data }}>
    {children}
  </PostContext.Provider>
)
// Consumer
const {자식에게 줄 data} = usePostContext()

return (
// 자유롭게 사용
)

⚠️ Context API를 무분별하게 사용하지 말기

  1. Provider가 변경되면 Consumer와 관련된 컴포넌트들이 전부 리렌더링되게 때문에 성능 이슈가 발생함.
  2. Consumer는 Provider가 필요하기 때문에 컴포넌트의 의존성이 높아짐.
  3. 컴포넌트는 순수할 수록 좋음
  • 사이드 이펙트 방지
  • 확장에 용이
  • 테스트 용이

axios

브라우저 | Node.js에서 사용가능한 HTTP 클라이언트 라이브러리.

react router

<Switch>
  <Redirect path="/" to="/login"/>
  <Route path="/login" component={Login} />
  <Route path="/signup" component={Signup} />
</Switch>
  • Switch
    여러 개의 라우터 중 하나만 표시해주는 라우터
  • Redirect
    다른 페이지로 돌려주는 역할
    e.g, 주소가 "/" 이면 "/login"으로 돌려줌
  • Route
    컴포넌트를 화면에 띄워주는 역할

BrowserRouter

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from '@layouts/App';

render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.querySelector('#app'),
);

react router를 쓰기 위해선 App 컴포넌트를 BrowserRouter 컴포넌트로 감싸줘야 한다.

코드 스플릿팅

loadable 라이브러리

초기 렌더링 시 필요한 페이지만 불러오도록 하여 사용자 경험을 살리기.
1. pages 컴포넌트 ()
2. 서버 사이드 렌더링 안되는 친구들
용량이 엄청 큰 컴포넌트들은 서버 사이드 렌더링 안되게 코드 스플릿팅하면 용량 아낄 수 있음.

⭐️ page 단위로 코드 스플릿팅

// package.json
"dependencies": {
  "@loadable/component": "^5.14.1",
}

"devDependencies": {
  "@types/loadable__component": "^5.13.3",
}
// import Login from '@pages/Login'
// import Signup from '@pages/Signup'
const Login = loadable(() => import('@pages/Login'))  
const Signup = loadable(() => import('@pages/Signup'))
profile
💪🏻 아는 걸 설명할 줄 아는 개발자 되기
post-custom-banner

0개의 댓글