이전에 연산된 값을 재사용. 주로 성능을 최적화할 때 사용
useMemo를 사용안하면 input값을 바꿀 때도 countActiveUsers함수가 호출되는 문제가 발생한다. 활성 사용자 수를 세는 건 users에 변화가 있을 때만 세야되는건데, input값이 바뀔때에도 컴포넌트가 리렌더링 되며 불필요할때에도 호출하여서 자원이 낭비된다.
이러한 상황에는 useMemo를 사용하여 성능을 최적화한다.
Memo(memoized)는 이전에 계산한 값을 재사용 한다는 의미가 있다.
이메일을 입력한다고 치면 CreateUser컴포넌트의 email이라는 속성(props)가 바뀌게 되는데 이 값은 원래 App컴포넌트의 state입니다. 결국 input에 입력하는 행위는 App Component의 state를 바꾸게 되는 행위.
App의 State가 변경됐으니 App Component가 다시 렌더링되면서 countActiveUsers가 실행되면서 호출
const count = useMemo(() => countActiveUsers(users), [users]);
첫번째 파라미터에는 어떻게 연산할지 정의하는 함수, 두번째는 deps배열을 넣어준다.
이 배열 안에 넣은 내용이 바뀌면, 우리가 등록한 함수를 호출해서 값을 연산해주고, 만약 내용이 바뀌지 않았다면 이전에 연산한 값을 재사용한다.
App.js
// import logo from './logo.svg';
// import './App.css';
import React, { useRef, useState, useMemo } from "react";
import CreateUser from "./CreateUser";
import UserList from "./UserList";
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 = e => {
const {name, value} = e.target;
setInputs({
...inputs,
[name] : value
});
};
const [users, setUsers] = useState([
{
id: 1,
username: 'jini',
email: 'genie9105@gamail.com',
active: true
},
{
id: 2,
username: 'biki',
email: 'biki@gmail.com',
active: false
},
{
id: 3,
username: 'nado',
email: 'nado@gmail.com',
active: false
}
]);
const nextId = useRef(4); //useref의 초기값은 4
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
// setUsers([...users, user]); 1번째 방법
setUsers(users.concat(user)); //2번째 방법
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
));
};
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;
App안에 countActiveUsers 선언 시
const countActiveUsers = () => {
console.log('count active users..');
return users.filter(user => user.active).length;
}
UseList.js
import React 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)}
>
{username}
</b>
<span>({email})</span>
<button onClick={() => onRemove(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;
CreateUser.js
import React from "react";
//onChange는 이 텍스트(input)값이 바뀌게 될때, onCreate는 버튼을 눌렀을 때 새로운 항목을 등록해주는 함수
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;

이 글은 패스트캠퍼스 '프론트엔드(React)올인원패키지Online'을 수강하며 정리한 노트입니다.
https://fastcampus.co.kr/search?keyword=%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C