이롭게 현명하게
[React] 리액트 useMemo 본문
목차
useEffect란?
import
예시 코드
정리
[useEffect란?]
useEffect는 컴포넌트의 성능을 최적화하기 위해 사용된다.
Memo는 memoization를 의미한다. 메모리 넣기라는 의미로 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때 이전에 계산한 값을 재사용하는 것을 말한다.
동일한 계산의 반복 수행을 제거하여 프로그램 실행속도를 빠르게 하는 기술이다.
[import]
import React,{useMemo} from "react";
<형태>
const 변수명 = useMemo(()=>함수명(),[deps]);
첫 번째 파라미터 : 함수 형태
두 번째 파라미터 : deps배열을 넣어준다.
- 내용이 바뀌면 : 함수를 호출해서 값을 연산
- 내용이 바뀌지 않으면 : 이전에 연산한 값을 재사용
[예시 코드]
import React,{useRef,useState,useMemo} 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({
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 : 'uni',
email : 'uni@gmail.com',
active : true
},
{
id : 2,
username : 'dog',
email : 'dog@gmail.com',
active : false
},
{
id : 3,
username : 'cat',
email : 'cat@gmail.com',
active : false
}
]);
const nextId = useRef(4);
const onCreate = () =>{
const user = {
id: nextId.current,
username,
email
}
setUsers(users.concat(user));
setInputs({
username:'',
email:''
});
//console.log(nextId.current)
nextId.current +=1;
console.log(users)
}
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 = countActiveUsers(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;
return users.filter(user=> user.active).length;
user에서 active가 true인 것만 filtering 하여 length를 가져온다.
<useMemo를 사용하지 않았을 때>
const count = countActiveUsers(users);
useState를 사용하여 input 상태를 관리 중이다.
onChange 이벤트를 발생시켜 상태를 바꿀 때도 컴포넌트는 리렌더링 된다.
리렌더링 될 때마다 활성 사용자 수를 계속 count 하게 된다.
input 태그에 값을 입력할 때마다 활성사용자수를 불필요하게 count 한다.
이러한 문제를 해결하기 위해 useMemo를 사용한다.
<useMemo를 사용할 때>
const count = useMemo(()=>countActiveUsers(users),[users]);
useMemo는 특정 값이 바뀌었을 때만 특정 함수를 실행해서 연산하도록 처리하고 원하는 값이 바뀌지 않았다면 리렌더링할 때 이전에 만들어 뒀던 값을 재사용할 수 있게 해준다.
()=>countActiveUsers(users) : users가 업데이트될 때에만 호출이 되고 그렇지 않으면 이전에 만들어놨던 값을 재사용한다.
useMemo를 사용하면 input에 입력해도 문제가 발생하지 않는다.
useMemo를 사용하면 필요한 연산을 필요할 대만 사용할 수 있다.
// App.js //
import React,{useRef,useState,useMemo} 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({
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 : 'uni',
email : 'uni@gmail.com',
active : true
},
{
id : 2,
username : 'dog',
email : 'dog@gmail.com',
active : false
},
{
id : 3,
username : 'cat',
email : 'cat@gmail.com',
active : false
}
]);
const nextId = useRef(4);
const onCreate = () =>{
const user = {
id: nextId.current,
username,
email
}
setUsers(users.concat(user));
setInputs({
username:'',
email:''
});
//console.log(nextId.current)
nextId.current +=1;
console.log(users)
}
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]) // 최적화가 끝났다.
return (
<>
<CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate} />
<UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
<div>활성 사용자 수 : {count}</div>
</>
);
}
export default App;
// CreateUser.js //
import React from "react";
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;
// UserList.js //
import React,{useEffect} 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)}
>{user.username}</b> <span>{user.email}</span>
<button onClick={()=>onRemove(user.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;
[정리]
import React,{useMemo} from "react";
const 변수명 = useMemo(()=>함수명(),[deps]);
성능을 최적화할 때 사용한다.
첫 번째 인수 : 함수
두 번째 인수 : 배열 deps를 넣어준다.
두 번째 인수에 넣어준 배열의 값이 바뀔 때만 함수가 실행된다.
그렇지 않으면 이전의 값을 재사용한다.
잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊
댓글과 좋아요는 큰 힘이 됩니다!
'웹 개발 > React' 카테고리의 다른 글
[React] 리액트 컴포넌트(Component) 렌더링 (2) | 2024.01.10 |
---|---|
[React] 리액트 엘리먼트 (Element) (1) | 2024.01.08 |
[React] 리액트 useEffect (0) | 2024.01.04 |
[React] 리액트 배열에 항목 수정하기 (0) | 2024.01.03 |
[React] 리액트 배열에 항목 제거하기 (2) | 2024.01.02 |