컴포넌트는 Props가 변화하거나, setState로 변화하여서 re-render 되는 경우가 있따. 하지만 해당 컴포넌트에서 이러한 일이 일어나지 않고, 상위 컴포넌트에서 이러한 일이 일어난다면 하위 컴포넌트도 자동으로 re-render가 일어나는 경우가 있다.
나는 지금 Re-render가 될 필요가 없는데!!! 진짜 비효율적이야!!!
내 컴포넌트는 memorize 해놓앗다가, 정말 필요한 상황에만 re-render 하게 해주세요!!! 하는 기능이 바로 React.memo 기능입니다!
먼저 import를 해야 합니다.
import React, {useState, useEffect, useCallback} from 'react';
그리고 진짜 코드를 살펴봅시다.
const SubmitComponent = () => (
<PostSubmitDiv>
<PostSubmit>작성완료</PostSubmit>
</PostSubmitDiv>
);
이러한 코드를 다음과 같이 변경해야합니다.
const SubmitComponent = React.memo (() => (
<PostSubmitDiv>
<PostSubmit>작성완료</PostSubmit>
</PostSubmitDiv>
);
아니면 그냥 export 부분을 이렇게 바꾸어도 되죠?
export default React.memo(WriteTitle);
import { useState } from 'react';
import React from 'react';
const getAverage = numbers => {
console.log("평균값 계산 중 ...");
if (numbers.length === 0 ) return 0;
const sum = numbers.reduce((a,b) => a + b );
return sum / numbers.length;
}
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
return (
<div>
<input value = {number} onChange = {onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key = {index}>{value}</li>
))}
</ul>
<div>
<b>평균값 : </b> {getAverage(list)}
</div>
</div>
)
};
export default Average;
위의 코드는 예제코드이다! 위의 파일은 Average.js
인데, 위 파일을 랜더링 하기 위하여 App.js를 만들어준다.
import Average from './Average';
const App = () => {
return <Average />;
};
export default App;
이렇게 기본적인 세팅을 끝마친다. 먼저 화면이 랜더링될 때 함수가 처음으로 초기화되면서 불려와지니까 console에 log가 하나 찍힌다
원래 console이 찍히는 함수는 함수의 평균값을 구할 때만 찍혀야 되는데 input값을 변경할때마다 계속 계속 찍힌다.
얘 도대체 왜이러는 걸까?
input값이 변경되면서 onChange 함수가 불리게 되고, 그때마다 랜더링이 다시 일어나 모든 함수가 다시 불려와져서 getAverage 함수도 다시 주소를 할당받아 console이 찍히는 것입니다.
아 그러면 인풋 값이 바뀔 때에는 평균값을 다시 계산할 필요가 없네요~
랜더링하는 과정에서 특정 값이 바뀌었을 때에만 연산을 수행하고, 원하는 값이 바뀌지 않았다면 이전에 연산하였던 결과를 다시 사용하는 방식을 고수해야겠습니다.
import React from 'react';
const getAverage = numbers => {
console.log("평균값 계산 중 ...");
if (numbers.length === 0 ) return 0;
const sum = numbers.reduce((a,b) => a + b );
return sum / numbers.length;
}
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value = {number} onChange = {onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key = {index}>{value}</li>
))}
</ul>
<div>
<b>평균값 : </b> {avg}
</div>
</div>
)
};
export default Average;
코드를 이렇게 수정해볼 수 있겠습니다. useMemo
를 이용하여서 해당 함수를 감싸고, 두번째 인자값으로는 이 친구가 list가 변경되는지만 확인하기 위하여 list를 넘겨주었네요.
그리고 함수는 어짜피 객체로 취급될 수 있으니까, avg
라는 변수에 담아서 그 값을 그대로 출력할 수 있게끔 만들었습니다.