[FE] React - (2)

365.48km·2022년 12월 15일
0

[FE Study] React

목록 보기
2/3
post-thumbnail

1. 리액트에서 Props란 무엇인가?

  • 리액트에서 props는 프로퍼티(properties, 속성)의 줄임말로, 읽기만 가능하며(read-only)불변성을 지닌 요소를 의미한다.

  • 애플리케이션에서 props는 부모 컴포넌트부터 자식 컴포넌트로 전달되는 계층 구조를 따른다. 반대는 불가능하다.
    * 리액트는 단방향 데이터 흐름 모델을 사용하기 때문이다.

2. CRA란?

  • CRA(create-react-app)은 React의 공식 CLI(명령줄 인터페이스)로서, SPA개발 초기 세팅을 편리하게 할 수 있도록 한다.
  • 애플리케이션을 개발할 때 create-react-app을 사용하면 개발자가 빌드 구성을 직접하지 않아도 되기 때문에, 코드에만 집중할 수 있어 효율적으로 개발할 수 있다.

3. 리액트의 라이프사이클과 역할

리액트의 라이프사이클은 4가지로 설명할 수 있다.

Key Ponint 💡 mounnt, render , update , unMount

  • 여기서 mount는 DOM이 생성되고 웹 브라우저 상에서 나타나는 것을 뜻하고,
  • DOM이 제거되는 것은 unMount를 의미한다.
  • 컴포넌트는 ‘생성(mounting) -> 업데이트(updating) -> 제거(unmounting)’ 의 생명주기를 갖는다.
  • 생명주기의 때에 따라 어떤 작업을 처리해야 하는지 지정해줘야 불필요한 업데이트를 방지할 수 있다.
  • 리액트의 클래스 컴포넌트는 라이프사이클 메서드를 활용하고,
    함수형 컴포넌트는 Hook을 사용한다.
  1. 최초로 컴포넌트 객체가 생성될 때 한 번 수행되어지는 componentDidMount()
  2. 초기에 화면을 그려줄 때와 업데이트가 될 때 호출되는 render()가 있습니다.
  3. 그리고 컴포넌트의 속성 값 또는 상태값이 변경되면 호출되어지는 componentDidUpdate()
  4. 마지막으로 컴포넌트가 소멸될 때 호출되어지는 componentWillUnMount()가 라이프사이클의 역할을 한다.

1) 마운트(생성)

컴포넌트의 인스턴스가 생성되어, DOM에 삽입될 때 순서대로 호출된다.

1. constructor():

  • 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드이다. this.props, this.state에 접근할 수 있으며, 리액트 요소를 반환한다.
    setState를 사용할 수 없으며, DOM에 접근해선 안된다.

2. getDerivedStateFromProps():

  • props에 있는 값을 state에 동기화 시킬 때 사용하는 메서드

3. render():

  • UI를 렌더링하는 메서드

4. componentDidMount():

  • 컴포넌트가 웹 브라우저 상에 나타난 후 즉 첫 랜더링을 마친 후에 호출하는 메서드
    라이브러리나 프레임워크의 함수를 호출하거나 이벤트 등록, setTimeout, setInterval과 같은 비동기 작업을 처리하면 되고, setState 호출도 이 메서드에서 호출하는 경우가 많다.

2) 업데이트

Props나 state가 변경되면 랜더가 진행되며 순서대로 호출된다.

Key Ponint 💡 주의할 것은 업데이트 부분
1. props가 바뀔 때
2. state가 바뀔 때
3. 부모 컴포넌트가 리랜더링 될 때
4. this.foreceUpdate로 강제로 랜더링을 트리거할 때

1. getDerivedStateFromProps():

  • 이 메서드는 마운트 과정에서 호출되며, 업데이트가 시작하기 전에도 호출된다.
    props의 변화에 따라 state 값에도 변화를 주고 싶은 경우에 사용한다.

2. shouldComponentUpdate():

  • props또는 state를 변경했을 때, 리렌더링을 시작할지 여부를 지정하는 메서드
    true를 반환하면 다음 라이프사이클 메서드를 계속 실행하고,
    false를 반환하면 작업을 중지한다.

3. render():

  • 컴포넌트 리렌더링

4. getSnapshotBeforeUpdate():

  • 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드

5. componentDidUpdate():

  • 컴포넌트 업데이트 작업이 끝난 후 호출하는 메서드.

3) 언마운트(마운트해제)

1. componentWillUnmount():

  • 컴포넌트를 DOM에서 제거할 때 실행한다.
    이후에 컴포넌트는 다시 렌더링 되지 않으므로, 여기에서 setState()를 호출하면 안된다.

4. React Hook

Key Ponint 💡 리액트의 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동(hook inito)할 수 있게 해주는 함수이다.

  • Hook은 class안에서는 동작하지 않고, class없이 React를 사용할 수 있게 해준다.

1) React Hook을 도입한 목적

리액트 훅을 도입하게 된 목적은 여러가지가 존재한다.

  1. 컴포넌트에서 상태관련 로직을 사용할 때, Hook 이전에 재사용 가능한 로직을 사용하기 위해서는, render, props나 고차 컴포넌트와 같은 패턴을 사용했는데, 이런 패턴은 코드의 추적을 어렵게 만든다.
    Hook을 활용하면, 상태 관련 로직을 추상화해 독립적인 테스트와 재사용이 가능해 레이어 변화 없이 재사용할 수 있다.

  2. 두 뻔째 목적으 기존의 라이프사이클 메서드 기반이 아닌, 로직 기반으로 나눌 수 있어서 컴포넌트를 함수 단위로 잘게 쪼갤 수 있다.는 점에서 이점이 있다.

2) React Hook 사용 규칙 두 가지

1. 최상위에서만 Hook을 호출해야한다. (반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.)

  • 이 규칙을 따르면, 컴포넌트가 랜더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.

2. 리액트 함수 컴포넌트에서만 Hook을 호출해야하고, 일반 JS함수에서는 Hook을 호출해서는 안된다.

✨ Hook 종류
1. 기본 Hook
useState, useEffect, useContext
2. 추가 Hooks
useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, useDebugValue

5. useState

Key Ponint 💡
동적으로 바뀌는 값을 관리할 때 사용하며, 상태 유지 값그 값을 갱신하는 함수를 반환한다.

const [state, setState] = useState(initialState);
  • 최초로 랜더링을 하는 동안, 반환된 state는 첫 번째 전달된 인자(initialState)의 값과 같다.
  • setState함수는 state를 갱신할 때 사용된다.
setState(newState);
  • 다음 리랜더링 시에, useState를 통해 반환받은 첫 번째 값은 항상 갱신된 최신 state가 된다. 즉, initialState인자는 초기 랜더링 시에만 사용되며 이후의 랜더링 시에는 이 값은 무시된다.

6. useEffect

Key Ponint 💡
리액트 컴포넌트가 랜더링 될때마다 특정 작업(effect)을 실행할 수 있도록 하는 Hook component가 mount, update, unmount됐을 때 작업을 처리할 수 있다.

  • hook이 클래스 컴포넌트의 기능을 사용하기 위해서 만들어진 것이지만 함수 컴포넌트에서도 side effect를 사용할 수 있다.

1) 클래스형 컴포넌트에서는 생명주기 메소드를 사용할 수 있었는데, 이를 함수형 컴포넌트에서도 사용할 수 있게 되었다.
2) 즉, 라이프사이클 훅을 대체할 수 있게 되었다. (componentDidMount, componentDidUpdate, componentWillUnmount)

useEffect는 `useEffect(callbackFunc, dependecies)로 두개의 인자를 넣어 호출할 수 있다.
1. useEffect(callBackFunc);
2. useEffect(callBackFunc, []);
3. useEffect(callBackFunc, [state1, state2]);
4. useEffect(()=>{ return(() => func()) });

① 의 경우 랜더링이 될 때마다 (컴포넌트가 마운트 된 후, 컴포넌트가 업데이트되고 난 후, 컴포넌트가 언마운트 되기 전에) 실행이 된다.
② depencies에 []를 넣어주면, 컴포넌트가 최초 랜더링되었을 때만 실행이 된다.
최초 랜더링 + state1 또는 state2가 변경이 되었을 때, 실행이 된다. 즉, 생명주기 메소드의 componentDidUpdate, getDerivedStateFromProps의 역할을 수행한다.
④ clean-up함수로 useEffect안에서 return 할 때 실행된다. 만약, 컴포넌트가 언마운트 될 때 이벤트 리스너를 통해 이벤트를 추가했다면, 컴포넌트가 언마운트 될 때 이벤트를 삭제해주어야 한다.그렇지 않으면, 컴포넌트가 리랜더링 될 때마다 새로운 이벤트 리스너가 핸들러에 바인딩 될 수 있다. 이는, 자주 리랜더링 될 경우 메모리 누수가 발생할 수 있다.

useEffect(()=>{
	console.log("useEffect!!");     
    return () => {console.log("cleanup!!")};
})
  • 컴포넌트가 랜더링될 때마다 console.log("useEffect!!")을 수행하고, 컴포넌트가 unmount될 때, console.log("useEffect!!")console.log("cleanup!!")를 수행한다.

Key Ponint 💡 effect 타이밍
useEffect로 전달된 함수는 컴포넌트 렌더링 - 화면 업데이트 - useEffect실행 순으로 실행이 된다. 즉, useEffect실행이 최초 렌더링 이후에 된다.

Key Ponint 💡 화면을 다 그리기 이전에 동기화되어야 할 때,
useLayoutEffect()를 활용하여 컴포넌트 랜더링 - useLayoutEffect 실행 - 화면 업데이트 순으로 effect를 실행할 수 있다.

7. useRef

Key Ponint 💡 React에서 DOM요소를 가져올 때 사용한다.
useRef는 리랜더링을 하지 않는다. 컴포넌트의 속성만 조회&수정 한다. 불필요한 리랜더링 방지를 위해서 useRef를 사용한다.


function App() {
  const [name, setName] = useState("")
  const ref = useRef("")

  const handleName = () => {
    setCurrentName(ref.current.value)
  }

  return (
    <>
      <input ref={ref} />
      <button onClick={handleName}>제출</button>
    </>
  )
}

export default App
  • ref.current.value를 통해 input에 있는 현재 value 값을 가져와서 제출하도록 한다. 실행하면, 화면을 처음 받아올 때와 제출 버튼을 눌렀을 때만 redering이 일어나게 된다.

8. useCallback

Key Ponint 💡 useCallback은 메모이제이션하기 위해서 사용되는 hook함수이다. 첫번째 인자로 넘어온 함수, 두번째 인자로 넘어온 배열 내의 값이 변경될 떄까지 저장하고 재사용할 수 있게 해준다.

  • useCallback은 변수가 선언되어지면 해당 함수가 실행되어진다. 그 후에 deps의 변경을 통해 값이 변경이 되면 새로운 함수를 return하고, 값이 변경이 되어지지 않는다면 기존 함수를 return한다.
const memizedCallback = useCallback(함수, 배열)
//App.js

import React, { useState, useCallback } from "react"
import List from "./List"

function App() {
  const [number, setNumber] = useState(1)
  const [dark, setDark] = useState(false)

  const getItems = useCallback(() => {
    return [number, number + 1, number + 2]
  }, [number])

  const theme = {
    backgroundColor: dark ? "#333" : "#fff",
    color: dark ? "#fff" : "#333",
  }

  return (
    <div style={theme}>
      <input
        type="number"
        value={number}
        onChange={e => setNumber(parseInt(e.target.value))}
      />
      <button onClick={() => setDark(prevDark => !prevDark)}>테마 변경</button>
      <List getItems={getItems} />
    </div>
  )
}

export default App

9. useMemo

Key Ponint 💡 성능 최적화를 위하여 연산된 값을 useMemo Hook을 사용하여 재사용하는 방법이다. 기존에 수행한 연산의 결과값을 어딘가에 저장해두고 동일한 입력이 들어오면 재활용한다.

  • 이러한 메모이제이션을 통해서 중복 연산을 피할 수 있기 때문에 메모리를 조금 쓰면서 성능의 최적화를 할 수 있다.

10. useCallback과 useMemo의 차이

  • useMemo는 특정 결과 값을 재사용하여 연산하는 반면에
  • useCallback은 특정 함수를 새로 만들지 않고, 재사용하고 싶을 때 사용하도록 한다.
    이 둘은 deps 리스트를 이용하여 변경값에 대해서 변경이 반영되도록 한다.
profile
이게 마즐까?

0개의 댓글