일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- AuthenticatoinProvide
- REACT
- Filter
- Crawling
- gradle
- OpenStack
- Pender
- cloud native
- Spring Security
- 리액트
- preventdefault
- MFA
- tasklet
- SWAGGER
- T-OTP
- cheerio
- SpringRESTDocs
- Spring REST Docs
- Reduxpender
- axios
- SpringBoot
- vue
- openapi3
- MSA
- JavaScript
- vuejs
- stopPropogation
- UsernamePasswordAuthenticationFilter
- Spring Batch
- Flyway
- Today
- Total
Miracle Morning, LHWN
17. React.memo 를 이용하여 컴포넌트 리렌더링을 방지하기 본문
# React.memo 를 이용하면, 컴포넌트의 props 가 바뀌지 않았을 때 리렌더링을 방지하여 컴포넌트의 리렌더링 성능 최적화를 해줄 수 있다.
→ 리렌더링이 필요한 상황에서만 하도록 설정할 수 있는 것이다!
// CreateUser.js
import React from 'react';
const CreateUser = ({ username, email, onChange, onCreate }) => {
return (
...
export default React.memo(CreateUser);
// UserList.js
import React from 'react';
const User = React.memo(function User({ user, onRemove, onToggle }) {
return (
...
});
function UserList({ users, onRemove, onToggle }) {
return (
...
);
}
export default React.memo(UserList);
이렇게 모든 컴포넌트에 React.memo 를 감싸줌으로써 input 을 수정하더라도 UserList 가 렌더링 되지 않는다.
그런데!! User 중 하나라도 수정하면 모든 User 들이 리렌더링되고, CreateUser 도 리렌더링이 되고 있다..
왜 그럴까?
users 배열이 바뀔 때마다 onCreate, onToggle, onRemove 함수가 새로 만들어지기 때문이다. (deps에 users 가 들어있기 때문에
배열이 바뀔 때마다 함수가 새로 만들어진다.)
const onCreate = useCallback(() => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
}, [users, username, email]);
const onRemove = useCallback(
id => {
// user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
// = user.id 가 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]
);
이걸 또 최적화 하기 위해서는 deps 에서 users 를 지우고, 함수 안에서 현재 useState 로 관리하는 users를 참조하지 않게 하는 것이다.
이는 함수형 업데이트를 통해 구현이 가능하다. 함수형 업데이트를 하면 setUsers 에 등록하는 콜백함수의 파라미터에서 최신 users 를 참조할 수 있기 때문에 deps 에 users 를 넣지 않아도 된다.
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({
username: '',
email: ''
});
const { username, email } = inputs;
const onChange = useCallback(e => {
const { name, value } = e.target;
setInputs(inputs => ({
...inputs,
[name]: value
}));
}, []);
const [users, setUsers] = useState([
{
id: 1,
username: 'velopert',
email: 'public.velopert@gmail.com',
active: true
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false
}
]);
const nextId = useRef(4);
const onCreate = useCallback(() => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users => users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
}, [username, email]);
const onRemove = useCallback(id => {
// user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
// = user.id 가 id 인 것을 제거함
setUsers(users => users.filter(user => user.id !== id));
}, []);
const onToggle = useCallback(id => {
setUsers(users =>
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;
# 리액트 개발을 할 때 useCallback, useMemo, React.memo 는 컴포너느의 성능을 실제로 개선할 수 있는 상황에서만 사용해야 한다.
가령, User 컴포넌트에 b 와 button 에 onClick 으로 설정해준 함수들은 useCallback 으로 재사용한다고 해서 리렌더링을 막을 수 있는 것은 아니므로 굳이 사용할 필요가 없다.
또한, 렌더링 최적화하지 않을 컴포넌트에 React.memo 를 사용하는 것은 불필요한 props 비교만 하는 것이기 때문에
실제로 렌더링을 방지할 수 있는 상황에만 사용해야 한다.
# React.memo 에서 특정 값들만 비교하기
export default React.memo(
UserList,
(prevProps, nextProps) => prevProps.users === nextProps.users
);
두 번째 파라미터에 propsAreEqual 함수를 이용해서 특정 값들만 비교할 수도 있다.
하지만, 잘못 사용할 경우 의도치 않은 버그들이 발생할 수 있다. 함수형 업데이트로 전환을 안했는데 이렇게 users 만 비교하게 되면,
onToggle 과 onRemove 에서 최신 users 배열을 참조하지 않으므로 심각한 오류가 발생할 수 있다.
출처 : https://react.vlpt.us/basic/19-React.memo.html
'IT 기술 > [React] 기본' 카테고리의 다른 글
19. Custom Hook 만들어보기 (0) | 2021.05.25 |
---|---|
18. useReducer 를 사용해서 상태(State) 업데이트 로직 분리해보기 (0) | 2021.05.25 |
16. useCallback 이용하여 함수 재사용하기 (0) | 2021.05.25 |
15. useMemo 를 이용해서 연산된 값을 재사용 (0) | 2021.05.25 |
14. useEffect로 마운트, 언마운트, 업데이트 시 특정 작업 설정해보기 (0) | 2021.05.25 |