
# React.memo
- 리액트에서 제공하는 고차 컴포넌트(HOC)
- 고차 컴포넌트? 어떠한 컴포넌트를 인자로 받아서 최적화된 컴포넌트를 반환해주는 함수
- 최적화된 컴포넌트는 props check를 통해 자신이 받는 props에 변화가 있는지 확인한 후 있다면 렌더링 해주고 없다면 기존에 있던 내용을 재사용 해준다.
- 오직 props 변화에만 의존하는 최적화 방법
React.memo가 필요할 때?
1. 컴포넌트가 같은 Props로 자주 렌더링 될 때
2. 컴포넌트가 렌더링이 될때마다 복잡한 로직을 처리해야 할 때
# 예제 1
부모 컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const [childAge, setChildAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
const incrementChildAge = () => {
setChildAge(childAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
return (
<div style={{border:'2px solid navy', padding:'10px'}}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<button onClick={incrementChildAge}>자녀 나이 증가</button>
<Child name={'홍길동'} age={childAge} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({name, age}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>name: {name}</p>
<p>age: {age}</p>
</div>
);
}
export default Child;
- 이때 부모 나이 증가 버튼을 클릭하면서 업데이트 되어 렌더링이 일어나는데, 부모 컴포넌트로 부터 props를 받는 자녀 컴포넌트도 렌더링이 일어나게 된다.
- 하지만 굳이 부모 나이 증가 버튼을 클릭해서 부모 나이만 변경할때 자녀 컴포넌트가 렌더링 될 필요는 없다.
불필요한 렌더링을 줄이기 위해 props가 업데이트 되지 않았다면 최적화를 시켜줄 수 있다.
import React from 'react';
const Child = ({name, age}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>name: {name}</p>
<p>age: {age}</p>
</div>
);
}
export default React.memo(Child);
- 함수 자체를 React.memo로 감싸줘도 되고 맨밑에 내보내는 함수명에 감싸줘도 된다.
# 예제 2
부모컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
const name = {
lastName: '홍',
firstName: '길동',
}
return (
<div style={{border:'2px solid navy', padding:'10px'}}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={name} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({name}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>성: {name.ChildlastName}</p>
<p>이름: {name.firstName}</p>
</div>
);
}
export default React.memo(Child);
이때 부모 나이 증가버튼을 클릭하여 업데이트하면 어떻게 될까?
→ 부모와 자녀컴포넌트가 둘 다 렌더링 된다
React.memo를 통해 최적화를 시켜줬음에도 불필요한 렌더링이 일어나는 이유는?
- 전달해준 props이 객체이기 때문,
- 객체타입은 값이 저장되는게 아닌 메모리주소가 저장되는 타입이다.
- 따라서 렌더링 될 때마다 함수가 초기화되며 변수 또한 초기화가 되는데 그때 마다 각각 다른 메모리주소를 받는다.
- 내용은 같아도 메모리주소가 달라지기 때문에 업데이트된걸로 간주되어 렌더링 된다.
이때 useMemo를 사용해서 해결해 줄 수 있다.
const name = useMemo(() => {
return{
lastName: '홍',
firstName: '길동',
};
}, []);
# 예제 3
부모컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
const tellMe = () => {
console.log('길동아 사랑해🎉');
};
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={'홍길동'} tellMe={tellMe} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({ name, tellMe }) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>이름: {name}</p>
<button onClick={tellMe}>엄마 나 사랑해?</button>
</div>
);
};
export default React.memo(Child);
- 이때도 예제2와 같이 부모 나이 증가버튼을 클릭하니 자녀 컴포넌트까지 렌더링이 된다. 전달해준 함수가 객체이기 때문이다.
이때 useCallback을 사용해서 해결해 줄 수 있다.
const tellMe = useCallback(() => {
console.log('길동아 사랑해🎉');
}, []);
- useMemo는 어떠한 값을 기억할 때 사용
- useCallback은 어떠한 함수를 기억할 때 사용
📌 참고
별코딩 | 리액트 훅스 시리즈
'Front-end > React' 카테고리의 다른 글
[React] CSR (클라이언트 사이드 렌더링) 과 SSR (서버 사이드 렌더링) (0) | 2023.03.07 |
---|---|
[React] React Hooks : useReducer (0) | 2023.03.03 |
[React] React Hooks : useCallback (0) | 2023.02.27 |
[React] React Hooks : useMemo (0) | 2023.02.24 |
[React] React Hooks : useContext (0) | 2023.02.22 |

# React.memo
- 리액트에서 제공하는 고차 컴포넌트(HOC)
- 고차 컴포넌트? 어떠한 컴포넌트를 인자로 받아서 최적화된 컴포넌트를 반환해주는 함수
- 최적화된 컴포넌트는 props check를 통해 자신이 받는 props에 변화가 있는지 확인한 후 있다면 렌더링 해주고 없다면 기존에 있던 내용을 재사용 해준다.
- 오직 props 변화에만 의존하는 최적화 방법
React.memo가 필요할 때?
1. 컴포넌트가 같은 Props로 자주 렌더링 될 때
2. 컴포넌트가 렌더링이 될때마다 복잡한 로직을 처리해야 할 때
# 예제 1
부모 컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const [childAge, setChildAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
const incrementChildAge = () => {
setChildAge(childAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
return (
<div style={{border:'2px solid navy', padding:'10px'}}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<button onClick={incrementChildAge}>자녀 나이 증가</button>
<Child name={'홍길동'} age={childAge} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({name, age}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>name: {name}</p>
<p>age: {age}</p>
</div>
);
}
export default Child;
- 이때 부모 나이 증가 버튼을 클릭하면서 업데이트 되어 렌더링이 일어나는데, 부모 컴포넌트로 부터 props를 받는 자녀 컴포넌트도 렌더링이 일어나게 된다.
- 하지만 굳이 부모 나이 증가 버튼을 클릭해서 부모 나이만 변경할때 자녀 컴포넌트가 렌더링 될 필요는 없다.
불필요한 렌더링을 줄이기 위해 props가 업데이트 되지 않았다면 최적화를 시켜줄 수 있다.
import React from 'react';
const Child = ({name, age}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>name: {name}</p>
<p>age: {age}</p>
</div>
);
}
export default React.memo(Child);
- 함수 자체를 React.memo로 감싸줘도 되고 맨밑에 내보내는 함수명에 감싸줘도 된다.
# 예제 2
부모컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
const name = {
lastName: '홍',
firstName: '길동',
}
return (
<div style={{border:'2px solid navy', padding:'10px'}}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={name} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({name}) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>성: {name.ChildlastName}</p>
<p>이름: {name.firstName}</p>
</div>
);
}
export default React.memo(Child);
이때 부모 나이 증가버튼을 클릭하여 업데이트하면 어떻게 될까?
→ 부모와 자녀컴포넌트가 둘 다 렌더링 된다
React.memo를 통해 최적화를 시켜줬음에도 불필요한 렌더링이 일어나는 이유는?
- 전달해준 props이 객체이기 때문,
- 객체타입은 값이 저장되는게 아닌 메모리주소가 저장되는 타입이다.
- 따라서 렌더링 될 때마다 함수가 초기화되며 변수 또한 초기화가 되는데 그때 마다 각각 다른 메모리주소를 받는다.
- 내용은 같아도 메모리주소가 달라지기 때문에 업데이트된걸로 간주되어 렌더링 된다.
이때 useMemo를 사용해서 해결해 줄 수 있다.
const name = useMemo(() => {
return{
lastName: '홍',
firstName: '길동',
};
}, []);
# 예제 3
부모컴포넌트
import React, { useState } from 'react';
import './App.css';
import Child from './Child';
function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log('👨👩👧부모 컴포넌트가 렌더링이 되었어요');
const tellMe = () => {
console.log('길동아 사랑해🎉');
};
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h1>👨👩👧부모</h1>
<p>age: {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={'홍길동'} tellMe={tellMe} />
</div>
);
}
export default App;
자녀컴포넌트
import React from 'react';
const Child = ({ name, tellMe }) => {
console.log('👩🏼자녀 컴포넌트가 렌더링이 되었어요');
return (
<div style={{ border: '2px solid navy', padding: '10px' }}>
<h3>👩🏼자녀</h3>
<p>이름: {name}</p>
<button onClick={tellMe}>엄마 나 사랑해?</button>
</div>
);
};
export default React.memo(Child);
- 이때도 예제2와 같이 부모 나이 증가버튼을 클릭하니 자녀 컴포넌트까지 렌더링이 된다. 전달해준 함수가 객체이기 때문이다.
이때 useCallback을 사용해서 해결해 줄 수 있다.
const tellMe = useCallback(() => {
console.log('길동아 사랑해🎉');
}, []);
- useMemo는 어떠한 값을 기억할 때 사용
- useCallback은 어떠한 함수를 기억할 때 사용
📌 참고
별코딩 | 리액트 훅스 시리즈
'Front-end > React' 카테고리의 다른 글
[React] CSR (클라이언트 사이드 렌더링) 과 SSR (서버 사이드 렌더링) (0) | 2023.03.07 |
---|---|
[React] React Hooks : useReducer (0) | 2023.03.03 |
[React] React Hooks : useCallback (0) | 2023.02.27 |
[React] React Hooks : useMemo (0) | 2023.02.24 |
[React] React Hooks : useContext (0) | 2023.02.22 |