Programming/JavaScript

[React] 리액트 라이프사이클, Hooks 알아보기

 

웹게임 가위바위보

 

본 강의에서는 react의 component를 상속받은 class component를 사용한다.

React에서 extends Component 후 성능적 이슈가 있을지 react devtools로 확인 후 pure Component를 사용할지 결정

쓸데없이 리렌더링이 일어날 때는 pure Component로 전환한다.

 

가위바위보 이미지(한개)를 css로 세가지로 보여줄 수 있다

 

background-postion을 통해 하나의 이미지의 부분부분을 재조명해준다

 


 

React life cycle

 

클래스 컴포넌트의 경우 -> constructor -> render -> ref (있을 경우) -> componentDidMount

-> (setState/props 의 값이 변경될 때 -> shouldComponentUpdate(true) -> render -> componentDidUpdate)

-> 부모 컴포넌트가 현재 컴포넌트 제거시 -> componentWillUnmount -> 컴포넌트 소멸

 

componentDidMount(){ } // 컴포넌트가 첫 렌더링된 후, 여기에 비동기 요청을 많이 한다.

componentDidUpdate(){ } // 리렌더링 후

componentWillUnmount(){ } // 컴포넌트가 제거되기 직전, 비동기 요청의 정리를 많이 한다.

 

 

** hooks 에는 라이프사이클 메소드가 없지만 useEffect가 라이프사이클 메소드의 역할을 해준다.

    단 useEffect의 경우 두번째 인자값을 넣을 경우 해당 state의 변화감지시 컴포넌트 전체가 리렌더링 되기 때문에 주의해야한다.

useEffect(() => { // componentDidMount, componentDidUpdate 역할(1대1 대응은 아님)
  interval.current = setInterval(changeHand, 100);
  
  return () =>{ // 두번째 인자가 빈값일 때 componentWillUnmount 역할
  	clearInterval(interval.current)
  }

}, [imgCoord]); // 두번째 인자가 있을때 componentDidMount 와 componentDidUpdate 둘 다 수행

 

** class 컴포넌트와 hooks 의 라이플사이클 비교

     - useEffect는 [ ] 인자값으로 update될 state를 지정한다면, 

       클래스의 경우 componentDidMount나 componentDidUpdate에서 모든 state를 조건문으로 분기 처리한다.

       (state 별로 처리 내용이 다르면 useEffect가 여러개가 될 수 있다.)

 


리액트 Hooks

 

useRef

      - getElementById, querySelector 와 같이 특정 DOM을 선택해야되는 상황에서 사용

      - 컴포넌트 안에서 조회 및 수정 할 수 있는 변수를 관리하는 역할

        (변수값이 변해도 리렌더링되지 않음, 설정후 바로 조회가능)

 

      [ 관리할수 있는 변수 ]

      1. setTimeout, setInterval 을 통해서 만들어진 id

      2. 외부 라이브러리를 사용하여 생성된 인스턴스

      3. scroll 위치

      

      [사용방법]

      1. useRef() 를 사용하여 Ref 객체를 생성한다.

      1-1. useRef() 를 사용 할 때 파라미터를 넣어주면, 이 값이 .current 값의 기본값이 된다.

      2. 생성한 객체를 선택하고 싶은 DOM 에 ref 값으로 설정한다.

      3. Ref 객체의 .current 값은 설정한 DOM 을 가르킨다.

      4. Ref 객체의 값(.current)을 수정할 때에는 .current 값을 수정하고, 조회시에도 .current를 조회한다.

const nameInput = useRef();

const onClick = () => {
    nameInput.current.focus();
}

const nextId = useRef(4);
const onCreate = () => {
    // ...
    nextId.current += 1;
};
  
return(
    <input ref={nameInput} />
    <button onClick={onClick}>클릭</button>
)

 

 

useLayoutEffect 와 useEffect 비교

 

  useEffect

        - 컴포넌트 렌더링 - 화면 업데이트 - useEffect실행

        - 비동기적으로 실행됨

        - DOM과 인터렉션이 없는 경우에 사용(대부분 경우)

 

  useLayoutEffect

        - 컴포넌트 렌더링 - useLayoutEffect 실행 - 화면 업데이트

        - 동기적으로 실행됨

        - 렌더링 직후 DOM요소의 값을 읽을 때 유용함(scroll position등)

        - DOM을 mutate할 경우에 사용

 

useEffect를 사용할 경우 effect가 실행됨과 동시에 DOM에 mutation이 일어날 경우 flickering이 발생할 수 있다.

이러한 경우 useLayoutEffect를 사용해서 flickering(깜빡임)을 막을 수 있다.

결국 두 hook의 가장 큰 차이점은 실행 시점이고,

렌더링할 state가 이펙트 내에서 초기화되어야 할 경우, 사용자 경험을 위해 useLayoutEffect을 사용하는 편이 좋다.

 

로또추첨기 중 반복수행될 부분을 component화 하였다.

고차 컴퍼넌트(Higher Order Component, HOC)

 

    - HOC는 컴포넌트를 다른 컴포넌트로 감싸는 형태를 취하고 있고 컴포넌트를 인자로 받아 새로운 컴포넌트롤 다시 return한다. 

    - React.memo를 사용하면 PureComponent 역할을 한다.

 

React.memo

       [작동기전]

       - 컴퍼넌트가 React.memo()로 래핑 될 때, React는 컴퍼넌트를 렌더링하고 결과를 메모이징(Memoizing)한다.

       - 다음 렌더링이 일어날 때 props가 같다면, React는 메모이징(Memoizing)된 내용을 재사용한다.

        

       - 컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링을 하도록 설정한다.

       - 비슷한 역할을 하는 useCallback, useMemo, React.memo 는 렌더링 최적화로 컴포넌트의 성능을 실제로 개선할 때 사용한다.

       - React.memo 에서 두번째 파라미터에 propsAreEqual 이라는 함수를 사용하여 특정 값들만 비교를 하는 것도 가능하다.

 

useMemo()

       - 값을 메모이징해서 재사용한다.

       - useMemo의 두번째 인자가 변경되면 초기화된다.

function NameTag(props) {
	return useMemo( () => <div>{props.name}</div> , [props.name] )
}

useCallback()

       - 함수 자체를 메모이징해서 재사용한다.

       - useCallback의 두번째 인자가 변경되면 초기화된다.

       - useCallback은 상하위 컴포넌트 관계에서 상위 컴포넌트가 넘겨주는 props를 핸들링하는 역할을 하는데,

         하위 컴포넌트가 그 부분을 신경쓰지 않고 상위 컴포넌트의 렌더링 여부에 따라 자동으로 렌더링이 되면 무용지물이되기 때문에

         React.memo 또는 useMemo와 함께 사용되어야한다.

const memoizedCallback = useCallback(
	() => {doSomething(a,b);}, //inline callback
	[a, b], //dependency
);

Hooks 사용 tip

 

1. hooks를 한번 선언하면 순서를 지켜주어야 한다.

   따라서 조건문 안에는 절대 넣으면 안되고, 함수나 반복문, 다른 hooks 안에서 사용하면 안된다.

 

2. useEffect 패턴

useEffect(() => {
	//ajax
}, []); //componentDidMount에서만 실행


const mounted = useRef(false);
useEffect(()=>{
	if(!mounted.current){
    	mounted.current = true;
    } else {
    	//ajax
    }
}, [바뀌는 값]); //componentUpdate에서만 실행

 

 

 

 


출처 👇👇👇 

강의정보  👇👇👇

더보기

플랫폼 : 인프런

강의 : 웹 게임을 만들며 배우는 React 

강사 : 제로초(조현영)

개발환경 : vscode, react

url : https://www.inflearn.com/course/web-game-react