hooks-useMemo

❓What is useMemo

  • μ»΄ν¬λ„ŒνŠΈ μ΅œμ ν™”μ— μ‚¬μš©λ˜λŠ” λŒ€ν‘œμ μΈ 훅이며, λΉ„μŠ·ν•œ ν›…μœΌλ‘œλŠ” useCallback이 μžˆλ‹€.

  • memoλž€? Memoization 을 λœ»ν•œλ‹€.

  • λ™μΌν•œ 값을 λ¦¬ν„΄ν•˜λŠ” ν•¨μˆ˜λ₯Ό 반볡적으둜 ν˜ΈμΆœν•΄μ•Ό ν•  λ•Œ, κ°€μž₯ μ²˜μŒμ— μ‚¬μš©ν–ˆλ˜ 값을 λ©”λͺ¨λ¦¬μ— μ €μž₯ν•œλ‹€.

  • 즉, 자주 μ‚¬μš©λ˜λŠ” 값을 ν•„μš”ν•  λ•Œ λ§ˆλ‹€ μΊμ‹œμ—μ„œ κ°€μ Έμ™€μ„œ μ‚¬μš©ν•˜λŠ” 것이닀.

  • ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλŠ” μƒνƒœκ°€ 변경될 λ•Œ λ§ˆλ‹€ λ¦¬λ Œλ”λ§λ˜κ³ , κ·Έ λ•Œ λ§ˆλ‹€ λ‚΄λΆ€ λ³€μˆ˜κ°€ μ΄ˆκΈ°ν™”λœλ‹€.

  • κΌ­ ν•„μš”ν•  λ•Œλ§Œ μ μ ˆν•˜κ²Œ μ‚¬μš©ν•˜λŠ” 것이 μ„±λŠ₯에 μ’‹λ‹€.

예제 μ½”λ“œ

function loadSomeData(value: number): number {
  for (let i = 0; i < 999999999; i++) {}
  return value;
}

export default function Hello() {
  const [countA, setCountA] = useState(0);
  const [countB, setCountB] = useState(0);

  const result = loadSomeData(countA);

  return (
    <div>
      <div>countA: {result}</div>
      <div>countB: {countB}</div>
      <div>
        <input
          type='number'
          value={result}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
            setCountA(Number(e.target.value))
          }
        />
      </div>
      <div>
        <input
          type='number'
          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
            setCountB(Number(e.target.value))
          }
        />
      </div>
    </div>
  );
}
  • μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”λ§λ˜μžλ§ˆμž loadSomeData ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜κ³  λ”œλ ˆμ΄κ°€ κ±Έλ¦°λ‹€.

  • 2개의 인풋 κ°’ 쀑에 μ–΄λ–€ 것을 μ—…λ°μ΄νŠΈ ν•˜λ”λΌλ„ loadSomeData ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜μ–΄ λ”œλ ˆμ΄κ°€ κ±Έλ¦°λ‹€.

const result = useMemo(() => loadSomeData(countA), [countA]);
  • μœ„μ˜ μ½”λ“œμ—μ„œλŠ” useMemo λ₯Ό μ‚¬μš©ν•˜μ—¬ loadSomeData ν•¨μˆ˜μ— λŒ€ν•œ 값을 λ©”λͺ¨μ΄μ œμ΄μ…˜ν•˜λ„둝 μˆ˜μ •ν•œλ‹€.

  • 그러면 λ‘λ²ˆμ§Έ input 값은 λ”œλ ˆμ΄ 없이 변경이 κ°€λŠ₯ν•˜λ‹€.

  • 즉, loadSomeData ν•¨μˆ˜μ˜ 리턴 값이 된 countA useMemo의 μ˜μ‘΄μ„±λ°°μ—΄μ— μ„€μ •ν•˜μ—¬ 같은 μ»΄ν¬λ„ŒνŠΈ λ‚΄μ—μ„œ λ‹€λ₯Έ μƒνƒœ 값이 변경이 λ˜μ–΄λ„, countA의 값은 λ³€κ²½λ˜μ§€ μ•Šμ•„ λ”œλ ˆμ΄κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.


값이 μ•„λ‹ˆλΌ 객체라면?

export default function Hello() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState < User > { name: '', age: '' };

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setCount(Number(e.target.value));
  };

  const handleFormChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setUser((prevUser) => ({ ...prevUser, [e.target.name]: e.target.value }));
  };

  const nameAndAge = { ...user, nameAndAge: `${user.name}-${user.age}` };

  useEffect(() => {
    console.log('call!');
  }, [nameAndAge]);

  return (
    <div>
      <div>
        <input type='number' value={count} onChange={handleOnChange} />
      </div>
      <div>
        <span>{JSON.stringify(nameAndAge)}</span>
      </div>
      <hr />
      <div>
        <label htmlFor='name'>Name</label>
        <input
          type='text'
          name='name'
          value={user.name}
          onChange={handleFormChange}
        />
      </div>
    </div>
  );
}
  • μƒνƒœ 값이 2κ°œκ°€ μžˆλ‹€. ν•˜λ‚˜λŠ” μ›μ‹œκ°’μ„ κ°–λŠ” count, 또 λ‹€λ₯Έ ν•˜λ‚˜λŠ” user λΌλŠ” 객체

  • user 객체의 ν‚€ 값을 μΆ”κ°€ν•˜μ—¬ λ¦¬ν„΄ν•˜λ„λ‘ ν•˜κ³ , useEffectλ₯Ό μΆ”κ°€ν•˜μ—¬ μ˜μ‘΄μ„±λ°°μ—΄μ— nameAndAge μ„€μ •

  • μ΄λ ‡κ²Œ ν–ˆμ„ λ•Œ κΈ°λŒ€ν•˜λŠ” λ™μž‘μ€, user 의 값이 λ°”λ€Œμ—ˆμ„ λ•Œλ§Œ useEffectκ°€ 호좜되고, count 값이 λ°”λ€Œμ—†μ„ λ–„λŠ” useEffectκ°€ ν˜ΈμΆœλ˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.

  • κ·ΈλŸ¬λ‚˜ useEffect λŠ” count 값이 λ°”λ€Œλ˜μ§€ user 객체의 값이 λ°”λ€Œλ˜μ§€ μ–Έμ œλ‚˜ ν˜ΈμΆœλœλ‹€.

  • 즉, nameAndAge λΌλŠ” 객체가 맀번 μƒˆλ‘­κ²Œ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.

μ•„λž˜μ˜ μ½”λ“œμ™€ 같이 μˆ˜μ •ν•˜μž.

const nameAndAge = useMemo(() => {
  const data = { ...user, nameAndAge: `${user.name}-${user.age}` };
  return data;
}, [user.name]);

useEffect(() => {
  console.log('call!');
}, [nameAndAge]);

μ΄λ ‡κ²Œ ν•˜λ©΄ user 의 name 값이 useMemo의 μ˜μ‘΄μ„±λ°°μ—΄μ— μ„€μ •λ˜μ–΄, useEffectλŠ” user의 name 값이 변경될 λ•Œμ—λ§Œ μ‹€ν–‰λ˜κ²Œ λœλ‹€.

Last updated