React/Velopert's React

[React] Study #17 | useCallback

yevdev 2021. 10. 8. 11:07

๐Ÿ’กuseCallback

  • useCallback์€ useMemo์™€ ๋น„์Šทํ•œ Hook
  • useMemo๋Š” ํŠน์ • ๊ฒฐ๊ณผ๊ฐ’์„ ์žฌ์‚ฌ์šฉ
  • useCallback์€ ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ

 

์ด์ „์— App.js ์—์„œ ๊ตฌํ˜„ํ–ˆ๋˜ onCreate, onRemove, onToggle ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•ด๋ณด์ž

const onCreate = () => {
  const user = {
    id: nextId.current,
    username,
    email
  };
  setUsers(users.concat(user));

  setInputs({
    username: '',
    email: ''
  });
  nextId.current += 1;
};

const onRemove = id => {
  // user.id ๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ์›์†Œ๋งŒ ์ถ”์ถœํ•ด์„œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ฌ
  // = user.id ๊ฐ€ id ์ธ ๊ฒƒ์„ ์ œ๊ฑฐํ•จ
  setUsers(users.filter(user => user.id !== id));
};
const onToggle = id => {
  setUsers(
    users.map(user =>
      user.id === id ? { ...user, active: !user.active } : user
    )
  );
};
  • ์ด ํ•จ์ˆ˜๋“ค์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง„๋‹ค.
  • ์‚ฌ์‹ค, ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ ์ž์ฒด๋Š” ์‚ฌ์‹ค ๋ฉ”๋ชจ๋ฆฌ๋„, CPU๋„ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์ฐจ์ง€ ํ•˜๋Š” ์ž‘์—…์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ์„ ์–ธํ•œ๋‹ค๊ณ  ํ•ด์„œ ๊ทธ ์ž์ฒด๋งŒ์œผ๋กœ ํฐ ํ›„๊ฐ€ํ•˜ ์ƒ๊ธธ ์ผ์€ ์—†์ง€๋งŒ, ํ•จ์ˆ˜๋ฅผ ํ•„์š”ํ•  ๋•Œ๋งŒ ๋งŒ๋“ค๊ณ  ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์—ฌ์ „ํžˆ ์ค‘์š”ํ•˜๋‹ค.
  • ๋‚˜์ค‘์— ์ปดํฌ๋„ŒํŠธ์—์„œ props๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜์œผ๋ฉด Virtual DOM์— ์ƒˆ๋กœ ๋ Œ๋”๋ง ํ•˜๋Š” ๊ฒƒ ์กฐ์ฐจ ํ•˜์ง€ ์•Š๊ณ  ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฐ๊ณผ๋ฌผ์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์ตœ์ ํ™” ์ž‘์—…์„ ํ•˜๋ ค๋ฉด ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ด๋‹ค!

 

useCallback์„ ์‚ฌ์šฉํ•ด๋ณด์ž!

App.js

import React,{useRef, useState, useMemo, useCallback} from 'react'; // useCallback ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import UserList from './UserList';
import CreateUser from './CreateUser';

function countActiveUsers(users){
  console.log('ํ™œ์„ฑ ์‚ฌ์šฉ์ž ์ˆ˜๋ฅผ ์„ธ๋Š” ์ค‘...');
  return users.filter(user => user.active).length;
}

function App() {

  const [inputs, setInputs] = useState({
    username: '', email: ''
  })


  const {username, email} = inputs;

  // useCallback์œผ๋กœ ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ
  const onChange = useCallback ( e => {
    const {name, value} = e.target;
    setInputs({
      ...inputs,
      [name]: value
    })
  }, [inputs]
  );


  const [users, setUsers] = useState(
    [
      {id: 1, username: 'John', email: 'john@example.com',
      active: true,
    },
      {id: 2, username: 'Car', email: 'car@example.com',
      active: false,
    },
      {id: 3, username: 'lee', email: 'lee@example.com',
      active: false,
    },
    ]
)
    

const nextId = useRef(4);

// useCallback์œผ๋กœ ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ
const onCreate = useCallback(() => {

    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers(users.concat(user));

    setInputs({
      username: '',
      email: ''
    })
    nextId.current += 1;
},[users, username, email]);

// useCallback์œผ๋กœ ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ
const onRemove = useCallback(id => {
  setUsers(users.filter(user => user.id !== id))
},[users]);

const onToggle = useCallback(id => {
  setUsers(
    users.map(user => 
      user.id === id ? { ...user, active: !user.active} : user
    )
  )
},[users])

// useMemo ์‚ฌ์šฉ
const count = useMemo(() => countActiveUsers(users),[users]);

  return (   
    <>
      <CreateUser 
      username={username}
      email={email}
      onChange={onChange}
      onCreate={onCreate}
      />
      <UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
      <div>ํ™œ์„ฑ ์‚ฌ์šฉ์ž ์ˆ˜ : {count} </div>
    </>
  );
}

export default App;

๐Ÿšซ ์ฃผ์˜! ํ•จ์ˆ˜์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ ํ˜น์€ props๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ผญ, deps ๋ฐฐ์—ด์•ˆ์— ํฌํ•จ์‹œ์ผœ์•ผ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

  • ๊ฐ’์„ ๋„ฃ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค๋ฉด, ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ•ด๋‹น ๊ฐ’์„ ์ฐธ์กฐํ•  ๋•Œ ๊ฐ€์žฅ ์ตœ์‹  ๊ฐ’์„ ์ฐธ์กฐํ•  ๊ฒƒ์ด๋ผ๊ณ  ๋ณด์žฅ ํ•  ์ˆ˜ ์—†๋‹ค!

 

 


Reference

https://react.vlpt.us/basic/18-useCallback.html