함수형 컴포넌트는 state가 바뀔 때 마다 코드 전체가 재실행된다. 따라서 함수가 다시 만들어지고 그 함수를 props로 받는 자식
컴포넌트들이 불필요한 렌더링이 발생하게된다.
따라서 불필요한 렌더링 방지를 위해 useCallback을 사용하고 deps에 넣어 준 값이 변경되었을 때만 새로 함수를 생성한다.
아래의 App.js의 코드를 보면 onInputChange, onCreate, onRemove, onToggle 함수가 props로 자식 컴포넌트에 내려진다.
따라서 불필요한 렌더링을 막기위해 useCallback을 사용해보자.
import React, { useState, useRef, useMemo } from "react";
import UserList from "./UserList";
import CreateUser from "./CreateUser";
const countActiveUser = users => {
console.log("카운트");
return users.filter(user => user.active).length;
};
export default function App() {
const [inputs, setInputs] = useState({
username: "",
age: ""
});
const { username, age } = inputs;
const [users, setUsers] = useState([
{
id: 1,
username: "Kim",
age: 20
},
{
id: 2,
username: "Lee",
age: "30"
},
{
id: 3,
username: "Choi",
age: "40"
}
]);
const nextId = useRef(4);
const onInputChange = e => {
const { value, name } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onCreate = () => {
const user = {
username,
age,
id: nextId.current,
active: false
};
setUsers([...users, user]);
setInputs({
username: "",
age: ""
});
nextId.current += 1;
};
const onRemove = id => {
setUsers(
users.filter(user => {
return user.id !== id;
})
);
};
const onToggle = id => {
setUsers(
users.map(user => {
return user.id === id ? { ...user, active: !user.active } : user;
})
);
};
const count = useMemo(() => countActiveUser(users), [users]);
return (
<div>
<CreateUser
username={username}
age={age}
onChange={onInputChange}
onCreate={onCreate}
/>
<div>activeUser : {count}</div>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} />
</div>
);
}
import React, { useState, useRef, useMemo, useCallback } from "react";
import UserList from "./UserList";
import CreateUser from "./CreateUser";
const countActiveUser = users => {
console.log("카운트");
return users.filter(user => user.active).length;
};
export default function App() {
const [inputs, setInputs] = useState({
username: "",
age: ""
});
const { username, age } = inputs;
const [users, setUsers] = useState([
{
id: 1,
username: "Kim",
age: 20
},
{
id: 2,
username: "Lee",
age: "30"
},
{
id: 3,
username: "Choi",
age: "40"
}
]);
const nextId = useRef(4);
const onInputChange = useCallback(
e => {
const { value, name } = e.target;
setInputs({
...inputs,
[name]: value
});
},
[inputs]
);
const onCreate = useCallback(() => {
const user = {
username,
age,
id: nextId.current,
active: false
};
setUsers([...users, user]);
setInputs({
username: "",
age: ""
});
nextId.current += 1;
}, [users, username, age]);
const onRemove = useCallback(
id => {
setUsers(
users.filter(user => {
return user.id !== id;
})
);
},
[users]
);
const onToggle = useCallback(
id => {
setUsers(
users.map(user => {
return user.id === id ? { ...user, active: !user.active } : user;
})
);
},
[users]
);
const count = useMemo(() => countActiveUser(users), [users]);
return (
<div>
<CreateUser
username={username}
age={age}
onChange={onInputChange}
onCreate={onCreate}
/>
<div>activeUser : {count}</div>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} />
</div>
);
}