성능 최적화를 위해 연산된 값을 useMemo
라는 Hook 을 사용하여 재사용하는 방법
import React, { useState, useRef, useMemo } from "react";
import CreateUser from "./CreateUser";
import UserList from "./UserList";
// useMemo: 특정값이 바뀌었을 때만 특정 함수를 실행해서 연산하도록 처리
function countActiveUsers(users) {
console.log("활성 사용자 수 세는 중");
return users.filter((user) => user.active).length;
// active가 true인 사용자 필터링해 수를 연산해서 가져옴
}
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: "su",
email: "susu@gmail.com",
active: true,
},
{
id: 2,
username: "liz",
email: "lili@gmail.com",
active: false,
},
{
id: 3,
username: "ro",
email: "ro@gmail.com",
active: false,
},
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email,
};
setUsers(users.concat(user));
setInputs({
username: "",
email: "",
});
nextId.current += 1;
};
const onRemove = (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]);
// 이 함수는 users가 바뀔 때에만 호출되고, 그렇지 않으면 이전에 만든 값을 재호출한다.
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} />
<div>활성 사용자 수 : {count} </div>
</>
);
}
export default App;
// filter를 사용해서 특정 조건이 만족할 때만 추출
useMemo: 특정값이 바뀌었을 때만 특정 함수를 실행해서 연산하도록 처리
const count = useMemo(() => countActiveUsers(users), [users]);
첫번째 파라미터로 어떻게 연산할지 정의하는 함수,
두번째 파라미터로 deps 배열을 넣어준다.
이 배열 안에 내용이 바뀌면 등록한 함수를 호출해서 값을 연한하고, 내용이 바뀌지 않으면 이전에 연산한 값을 재사용한다.
Hook
함수로, 이전에 만들었던 함수를 새로 만들지 않고 재사용하는 방법
useMemo
와 비슷한데 함수를 위한 Hook
이다.
props가 바뀌지 않았다면, 이전에 만든 결과물을 재사용할 수 있게 하기 위해서는 함수도 재사용할 수 있게 만들어주어야 한다.
import React, { useState, useRef, useMemo, useCallback } 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 = useCallback(
(e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
},
[inputs]
);
// 의존하고 있는 상태 inputs를 넣어줌, inputs가 바뀔 때만 새로 만들어짐
const [users, setUsers] = useState([
{
id: 1,
username: "su",
email: "susu@gmail.com",
active: true,
},
{
id: 2,
username: "liz",
email: "lili@gmail.com",
active: false,
},
{
id: 3,
username: "ro",
email: "ro@gmail.com",
active: false,
},
]);
const nextId = useRef(4);
const onCreate = useCallback(() => {
const user = {
id: nextId.current,
username,
email,
};
setUsers(users.concat(user));
setInputs({
username: "",
email: "",
});
nextId.current += 1;
}, [username, email, users]);
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]
);
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;