성능 최적화를 위하여 연산된 값을 재사용하는 useMemo예제
send me email if you have any questions.
사용자 수 count(성능 최적화X)
import React, { useRef, useState } from 'react';
import UserList from './components/UserList';
import CreateUser from './components/CreateUser';
function countUsers(users){
console.log("counting users...");
return users.length;
}
function App() {
const [users, setUsers] = useState([
{
id: 1,
username: '임준호',
phonenumber: '010-0000-0000'
},
{
id: 2,
username: 'testuser1',
phonenumber: '010-1234-1234'
},
{
id: 3,
username: 'testuser2',
phonenumber: '010-2222-4444'
}
]);
const [inputs, setInputs] = useState({
username: '',
phonenumber: ''
});
const { username, phonenumber } = inputs;
const onChange = e => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
phonenumber
};
setUsers(users.concat(user))
setInputs({
username: '',
phonenumber: ''
});
nextId.current += 1;
};
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
const onUpdate = id => {
setUsers(
users.map(user =>
user.id === id ?
{ id: nextId.current, username: username, phonenumber: phonenumber }
: user
)
);
setInputs({
username: '',
phonenumber: ''
});
nextId.current += 1;
};
const count = countUsers(users);
return (
<div>
<CreateUser
username={username}
phonenumber={phonenumber}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onUpdate={onUpdate} />
<div>사용자 수 : {count}</div>
</div>
);
};
export default App;
App.js
랜더링된 유저의 수를 세는 countUsers구현
예제 실행결과
Console에 출력된 log를 보면 input의 값이 바뀔때에도 컴포넌트가 리렌더링 되므로 countUsers가 실행되는것을 볼 수 있다.
users의 변화가 있을 때만 countUsers가 호출된다면 기존에비해 효율성이 증대될 것이다.
참고로 React 문서에 따르면, log가 2번씩 찍히는 것은 React에서 의도된 기능이라고 한다.
useState를 사용한 함수형 컴포넌트가 두 번 실행되는 이유?
StrictMode에서 실행되는 이 기능은 사이드 이펙트를 발견할 수 있도록 도와준다.
What is Strict Mode?
index.js에서 볼 수 있는 이 기능은 애플리케이션 내의 잠재적인 문제를 알아내기 위한 도구라고 한다.
개발모드에서만 활성화 되기 때문에, 프로덕션 빌드에는 영향을 끼치지 않는다.
사용자 수 count(성능 최적화)
import React, { useRef, useState, useMemo } from 'react';
import UserList from './components/UserList';
import CreateUser from './components/CreateUser';
function countUsers(users){
console.log("counting users...");
return users.length;
}
function App() {
const [users, setUsers] = useState([
{
id: 1,
username: '임준호',
phonenumber: '010-0000-0000'
},
{
id: 2,
username: 'testuser1',
phonenumber: '010-1234-1234'
},
{
id: 3,
username: 'testuser2',
phonenumber: '010-2222-4444'
}
]);
const [inputs, setInputs] = useState({
username: '',
phonenumber: ''
});
const { username, phonenumber } = inputs;
const onChange = e => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
phonenumber
};
setUsers(users.concat(user))
setInputs({
username: '',
phonenumber: ''
});
nextId.current += 1;
};
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
const onUpdate = id => {
setUsers(
users.map(user =>
user.id === id ?
{ id: nextId.current, username: username, phonenumber: phonenumber }
: user
)
);
setInputs({
username: '',
phonenumber: ''
});
nextId.current += 1;
};
const count = useMemo(() => countUsers(users), [users]);
return (
<div>
<CreateUser
username={username}
phonenumber={phonenumber}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onUpdate={onUpdate} />
<div>사용자 수 : {count}</div>
</div>
);
};
export default App;
App.js
useMemo 의 첫 번째 파라미터에는 함수를, 두 번째 파라미터에는 deps 배열을 전달한다.
deps 배열 안의 값이 바뀌면 첫 번째 파라미터로 전달한 함수를 호출해서 값을 연산하고, 값이 바뀌지 않았다면 이전에 연산한 값을 재사용한다.
예제 실행결과
PREVIOUSuseEffect Example(Hook)