💡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
'React > Velopert's React' 카테고리의 다른 글
[React] Study #19 | useReducer : 상태 업데이트 로직 분리 (0) | 2021.10.09 |
---|---|
[React] Study # 18 | React.memo (0) | 2021.10.09 |
[React] Study # 16 | useMemo (0) | 2021.10.08 |
[React] Study #15 | useEffect (0) | 2021.10.08 |
[React] Study #14 | 배열 항목 수정하기 (0) | 2021.10.07 |