const onCreate = useCallback(() => {
const user = {
id: nextId.current,
height,
weight
}
setUsers(users.concat(user));
nextId.current += 1;
setInputs({
height: '',
wight: ''
});
}, [height, weight, users]);
const onChange = useCallback(e => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]:value
})
}, [inputs]);
const onToggle = useCallback(id => {
sestUsers(
users.map(
user =>
user.id === id
? { ...user, active: !user.active }
: user
)
);
}, [users]);
const onRemove = useCallback(id => {
setUsers(users.filter(user => user.id !== id);
}, [users]);
위 코드는 각자 state의 변경이 일어나기 때문에, App.js의 자식 컴포넌트인 각종 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({
height: '',
weight: ''
});
const { height, weight } = inputs;
const [users, setUsers] = useState([
{
id: 1,
height: 185,
weight: 75,
active: false,
},
{
id: 2,
height: 167,
weight: 50,
active: false,
},
{
id: 3,
height: 173,
weight: 80,
active: false,
}
]);
const nextId = useRef(4);
const onCreate = useCallback(() => {
const user = {
id: nextId.current,
height,
weight
}
setUsers(users => users.concat(user));
nextId.current += 1;
setInputs({
height: '',
weight: ''
});
}, [height, weight]);
const onChange = useCallback(e => {
const { name, value } = e.target;
setInputs(inputs => ({
...inputs,
[name]: value
}));
}, []);
const onToggle = useCallback(id => {
setUsers(users =>
users.map(
user =>
user.id === id
? { ...user, active: !user.active }
: user
)
);
}, []);
const onRemove = useCallback(id => {
setUsers(users => users.filter(user => user.id !== id);
}, []);
const count = useMemo(() => countActiveUsers(users), [users]);
return (
<>
<CreateUser
height={height}
weight={weight}
onCreate={onCreate}
onChange={onChange}
/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove} />
<div>
<b>활성 사용자 수 :</b>{count}
</div>
</>
);
}
export default App;
이런 식으로 함수영 업데이트를 진행해주면 App이 바뀌어도, callback측에서는 []안에 바뀐 state들이 들어있지 않으므로, 리렌더링을 진행하지 않는다.
따라서, 리렌더링 횟수를 줄이기 위해서 함수형 업데이트를 하는 것이다.