Lazy initial State, useMemo, useEffect

Mayton·2021년 8월 30일
0

React

목록 보기
1/10
post-thumbnail

React Function component를 이용해 코드를 작성하였다
API로 React페이지 구성하는 과정에서 useState로 선언되어 있는 값들 중 하나라도 변경되면 페이지가 지속해서 렌더링 되는 오류가 있었다
"Too many re-renders. React limits the number of renders to prevent an infinite loop." 와 같은 오류가 발생하였다

👉 오류 발생 원인

위의 코드에서 useEffect(getCoins()) 부분이 infinite rerendering을 일으키고 있었다
특히 다른 부분에서 mousepointer를 입력값으로 받고 있어서 mouspointer가 움직일 때마다 rendering이 되었다.

✅ 해결 방안은 lazy initial State(useEffect), useMemo가 있다

1.Lazy initial State

import { useState } from 'react'
  function getCount() {
    return Array(100000)
.fill(1)
      .reduce((acc, cur) => acc + cur, 0)
  }
  function App() {
    return (
<Counter /> )
  }
  function Counter() {
// handleClick를 클릭해서 리렌더링 될때마다 비싼 연산이 계속 일어난다. const expensivelyCaculatedCount = getCount()
const [count, setCount] = useState(expensivelyCaculatedCount)
    const handleClick = () => {
      setCount((previousCount) => previousCount + 1)
}
    return (
      <section>
        <span>{count}</span>
        <button onClick={handleClick}>Plus 1</button>
      </section>
 ) 
}

👉 "위의 코드에서는 useState의 초기값이 click을 할 때마다 계산이 된다" 따라서 arrow function을 이용하여 변경해주면 초기 mount시에만 초기 값이 계산되는 Lazy intial State를 사용할 수 있다

✅ 해결방안

 useState(()=>getCount())

✅ 맨 위의 코드는 아래와 같이 변경하면 될 것이다

 useEffect(()=>getCoins())

❌ 문제점이 이때 두가지 발생하게 된다
1. return 값이 필요없음에도 불구하고 getCoins()의 return 값을 지속해서 전달해주고 있다
2. dependency array가 사용되지 않아 useEffect의 이점을 전혀 사용 하지 못한다

위의 두가지 문제점을 모두 해결한 최종 코드는 아래와 같다

 useEffect(()=>{
   getCoins()
   return
 }, [coins])

2.useMemo

function getCount(fillNumber) {
    console.log('An expensive work is been executing...')
    return Array(100000)
      .fill(fillNumber)
      .reduce((acc, cur) => acc + cur, 0)
}

function Counter() {
    const [fillNumber, setFillNumber] = useState(1)
    const [text, setText] = useState('')
    const sum = getCount(fillNumber)
    
    const handleClick = () => {
      setFillNumber((previousNumber) => previousNumber + 1)
	}
    
    return (
      <section>
        <span>Sum: {sum}</span>
        <input value={text} onChange={(event) => setText(event.target.value)}/>
        <button onClick={handleClick}>
          Plus FillNumber 1
        </button>
      </section> )
}

function App() {
    return (
	<Counter />
    )}

👉 위에서도 선언된 값 text가 입력 될때마다 getCount의 함수가 지속해서 실행이되고 있다 만약에 Api를 렌더링 해오는 등 expensive 함수가 들어간다면 굉장히 버벅이는 웹페이지가 만들어질 것이다.

✅ 해결방안(useMemo)

useMemo(()=>getCount(fillNumber),fillnumber))

✅ 맨 위의 코드는 아래와 같이 변경하면 될 것이다

 useMemo(()=>getCoins(), coins))

useMemo

  • 단순한 값을 기억할 때 사용하며 rendering되는 와중에 실행된다
  • 통상적으로 렌더링 중에는 하지 않는 것은 useEffect에서 해야한다
  • useMemo는 최적화를 위해 사용될 수는 있지만 항상 최적화가 보장되지는 않는다

UseMemo는 React.memo를 이용해서 컴포넌트를 받을 수 있며 두번째 함수 값에 이전값과 현재 값을 비교하여 boolean을 반환하는 함수를 넣어 이전값과 비교하여 함수를 계산 할 수도 있다. useMemo의 자세한 사항은 다음 포스트에 다루어 보겠다

  
profile
개발 취준생

0개의 댓글