useState lazy initialization

이민석·2023년 1월 29일
1

Frontend

목록 보기
3/5

lazy initialization 이란?

const [value , setValue] = useState(0);

위와같이 useState를 사용하여, state를 설정할 수 있다.
만약, useState의 parameter로 함수의 리턴값을 전달하고 싶다면 어떨까?

function complexFunction() {
  	//복잡한 과정
  	console.log("complexFunction was executed");
	return value; 
}

const [value , setValue] = useState(complexFunction());

와 같이 작성하면, 컴포넌트가 리렌더링될때마다 console에 "complexFunction was executed"이 찍히는 것을 확인할 수 있다.

useState에 인자로 주는 함수가 초기화 될때만 실행되는 것이 아니라, 리렌더링될때도 실행되는 낭비가 발생하고 있는 것이다.

그렇다면, 다음과 같이 해보면 어떨까?

const [value , setValue] = useState(complexFunction);

처음 페이지가 렌더링 될때만 console에 "complexFunction was executed"이 찍히고, 이후에 리렌더링이 발생함에도 불구하고 console에는 로그가 나타나지 않는 것을 확인할 수 있을 것이다.

이것이 바로 lazy initialization이다.

useState의 초기값으로 복잡하고, 자원이 많이 필요한 함수를 전달하는 경우 리렌더링 될때 함수가 다시 실행되는 것을 막고, 성능을 향상 시킬 수 있다.

그렇다면, 위에서 예시로 든 useState의 인자로 함수를 전달했던 두가지 방법의 차이점은 무엇일까?

js에서 함수 호출 vs 함수 선언

자바스크립트에서 함수의 선언과 호출의 차이점을 명확히 이해하고 있는가?

function f(){
	console.log("f was executed");
  return 0;
}

f();

F = () => {
  console.log("F was executed");
  return 0;
}
F();

위의 예제에서 어떤것이 함수의 선언이고, 어떤것이 함수의 호출인지 구분할 수 있을 것이다.

필자는 react를 처음 배울때 다음과 같은 실수를 저지른 적이 있었다.


import React from 'react';

function Counter() {
  const onIncrease = () => {
    console.log('+1')
  }
  const onDecrease = () => {
    console.log('-1');
  }
  return (
    <div>
      <h1>0</h1>
      <button onClick={onIncrease()}>+1</button>
      <button onClick={onDecrease()}>-1</button>
    </div>
  );
}

이렇게 코드를 작성하면, 버튼을 누르지 않았음에도 불구하고, 새로고침을 할때마다 console에 log들이 찍힌다.

이유는 바로, button의 onClick에 함수의 선언!을 전달한 것이 아닌, 함수의 호출!을 전달했기 때문이다

기본적으로 button의 onClick으로는 함수의 선언을 전달해야 정상적으로 작동한다.
그리고, 함수의 호출을 전달할경우 return값인 undefined가 전달된다고 보면 된다.
결론적으로, 페이지가 리렌더링될때마다 함수가 실행되어, console에 로그들이 찍히게 되는 것이다.

...위에서의 상황과 비슷하지 않은가?

lazy initialization의 원리

function complexFunction() {
  	//복잡한 과정
  	console.log("complexFunction was executed");
	return value; 
}

const [value , setValue] = useState(complexFunction());

이렇게 작성하면, lazy initialization이 작동하지 않았다.
이유는 바로 useState의 parameter로 함수의 선언을 전달한 것이 아니라, 함수의 호출을 전달했기 때문이다!
함수의 호출을 전달한 경우에는 컴포넌트들이 리렌더링 될때마다 함수의 호출이 실행되기 때문에, complexFuntion이 실행된다.

function complexFunction() {
  	//복잡한 과정
  	console.log("complexFunction was executed");
	return value; 
}

const [value , setValue] = useState(complexFunction);

그러나, 위와 같이 작성하면, lazy initialization이 작동한다.
함수의 선언을 전달했기 때문이다.
useState는 state의 초기값을 설정할때만, complexFunction을 실행하고, 이후에 리렌더링 될때는 실행하지 않는다.

같은 원리로 lazy initialization을 위해서 다음과 같이 작성해도 된다.

const [value , setValue] = useState(()=>complexFunction());

추가적으로 react의 렌더링에 관한 좋은 포스트가 있으니 참고하면 매우 도움이 될 것 같다.
https://velog.io/@eunbinn/when-does-react-render-your-component#%ED%9D%90%EB%A6%84%EB%8F%84

0개의 댓글