이롭게 현명하게

[React] 리액트 useCallback 본문

웹 개발/React

[React] 리액트 useCallback

dev_y.h 2024. 1. 16. 18:32
728x90
반응형

※ 본 포스팅은 윈도우11 환경에서 패스트 캠퍼스 강의를 수강하며 정리한 내용입니다.

 


 

목차

 

useCallback이란?

import

예시 코드

정리

 


 


[useCallback이란?]

useCallback은 useMemo와 비슷하다.

useMemo : 특정 결괏값을 재사용할 때 사용

useCallback : 특정 함수를 새로 만들지 않고 새로 사용

 

useCallback을 사용하지 않는 함수들은 컴포넌트가 리렌더링 될 때마다 새로 만들어진다.

함수를 새로 만드는 것은 메모리, cpu가 리소스를 많이 차지하지는 것은 아니다.

함수를 새로 선언한다고 해서 그 자체만으로 큰 부하가 생기지 않는다.

한번 만든 함수를 재사용할 수 있을 때 재사용하는 것이 좋다.

나중에 컴포넌트들이 props가 바뀌지 않는다면 Virtual DOM에 리렌더링 조차 안 하게 할 수 있다.

만약 props가 바뀌지 않았다면 Virtual DOM을 새로 그리는 것이 아닌 이전에 만들어 뒀던 결과물을 재사용할 수 있다.

그 작업을 하려면 매번 함수가 새로 만들어지는 구조라면 최적화할 수 있다.

그러므로 함수도 재사용해 줘야 한다.

 


[import]

import React,{useCallback} from "react";

 

<형태>

const 변수명 = useCallback(()=>{수행해야할 문장},[deps 배열]);

deps 값을 넣지 않는다면 함수 내부에서 해당 상태들을 참조하게 될 때 가장 최신 상태를 참조하는 것이 아닌 이전의 것. 즉, 컴포넌트가 처음 만들어질 때인 예전 상태를 참조하게 된다.

useCallback 내부에서 참조하게 되는 상태 혹은 props로 받아오는 어떤 값이 있다면 넣어줘야 한다.

 


[예시 코드]

 

더보기

// 전체 코드

 

// App.js //

import React,{useRef,useState,useMemo,useCallback} from "react";
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;
  const onChange = useCallback(e =>{
    const {name,value} = e.target
    setInputs({
      ...inputs,
      [name]:value
    });
  },[inputs]); 
  const [users,setUsers] =useState([
    {
        id : 1,
        username : 'uni',
        email : 'uni@gmail.com',
        active : true
    },
    {
        id : 2,
        username : 'dog',
        email : 'dog@gmail.com',
        active : false
    },
    {
        id : 3,
        username : 'cat',
        email : 'cat@gmail.com',
        active : false
    }
]);


  const nextId = useRef(4);
  const onCreate = useCallback(() =>{
    const user = {
      id: nextId.current,
      username,
      email
      
    }
    setUsers(users.concat(user));
    setInputs({
      username:'',
      email:''
    });
    //console.log(nextId.current)
    nextId.current +=1;
    
  console.log(users)
  },[username,email,users]);

  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);

  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;

 

// CreateUser.js //
import React from "react";

function CreateUser({username,email,onChange,onCreate}){
    return(
        <div>
            <input name="username" placeholder="계정명" onChange={onChange} value={username}/>
            <input name="email" placeholder="이메일" onChange={onChange} value={email}/>
            <button onClick={onCreate}>등록</button>
        </div>
    );

}

export default CreateUser;

 

// UserList.js //
import React,{useEffect} from "react";

function User({user, onRemove,onToggle}){
    const {username,email,id,active}=user;
    return(
        <div>
            <b 
            style={{
                color: active? 'green': 'black',
                cursor : 'pointer'
            }}
            onClick={()=>onToggle(id)}
            >{user.username}</b> <span>{user.email}</span>
            <button onClick={()=>onRemove(user.id)}>삭제</button>
        </div>
    );
}

function UserList({users,onRemove,onToggle}){
    return(
        <div>
            {
                users.map(
                    user =>(<User user={user} key={user.id} onRemove={onRemove} onToggle={onToggle}/>)
                )
            }
        </div>
    );
}

export default UserList;

 

 

 

const onChange = useCallback(e =>{
    const {name,value} = e.target
    setInputs({
      ...inputs,
      [name]:value
    });
  },[inputs]);

[inputs] : 내부에서 의존하고 있는 값. deps값

useState를 통해 inputs를 관리하고 있다.

onChange 함수는 inputs가 바뀔 때만 함수가 새로 만들어지고 그렇지 않다면 기존에 만든 함수를 재사용하게 된다.

 


[정리]

import React,{useCallback} from "react";
const 변수명 = useCallback(()=>{수행해야할 문장},[deps 배열]);

useCallback : 특정 함수 재사용

useMemo : 특정 결괏값 재사용

컴포넌트에서 props가 바뀌지 않았으며 Virtual DOM에 새로 렌더링 하는 것조차 하지 않고 컴포넌트의 결과물을 재사용하는 최적화 작업을 하려면 함수 재사용 필수

deps 배열에 꼭 포함되어야 하는 것 : 함수 안에서 사용하는 state혹은 props

컴포넌트 렌더링 최적화 작업을 해주어야만 성능이 최적화 : useCallback & React.memo

 

 

 


잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊

댓글과 좋아요는 큰 힘이 됩니다!

 

 

728x90
반응형

'웹 개발 > React' 카테고리의 다른 글

[React] 리액트 useReducer  (0) 2024.01.18
[React] 리액트 React.memo  (0) 2024.01.17
[React] 리액트 State란?  (0) 2024.01.15
[React] 리액트 props 사용방법  (0) 2024.01.12
[React] 컴포넌트(Component) 만들기  (2) 2024.01.11
Comments