리액트 개발을 하다보면 눈에는 보이지 않지만 많은 컴포넌트들이 불필요하게 리렌더링 되는 경우들이 많다. 실제로 console.log를 찍어 확인해 보면 무수히 많은 로그들이 촤라라 올라오는 것을 확인할 수 있다. 오늘은 React.Memo를 사용해 컴포넌트를 최적화 하는 방법을 정리해 보려고 한다.
[ 컴포넌트가 렌더링 되는 경우 ]
1. 부모 컴포넌트가 렌더링 될 경우.
2. 전달받은 props 값이 업데이트 되었을 경우.
3. 컴포넌트 내 State가 변경되었을 경우.
전달받은 props 값이나 컴포넌트 내 State가 변경되지 않았을 경우에는 렌더링을 다시 할 이유가 없다. React.Memo는 props가 변경되지 않았을 경우 마지막 렌더링 결과를 재사용 함으로써 불필요한 리렌더링을 방지할 수 있다.
const MyComponent = React.memo(({props1, props2}) => {
return <></>
})
export default MyComponent;
또는
function MyComponent({props1, props2}){
return <></>
}
export default React.memo(MyComponent)
[app.js]
function App() {
console.log('App.js Rendering')
const [todoData,setTodoData] = useState([])
const [inputValue, setInputValue] = useState('')
const handleSubmit = (e) =>{
e.preventDefault()
let newTodo ={
id: Date.now(),
title: inputValue,
completed: false
}
setTodoData([...todoData,newTodo])
setInputValue('')
}
return (
<div className="flex items-center justify-center w-screen h-screen bg-blue-100 ">
<div className="w-full p-6 m-4 bg-white rounded shadow lg:w-3/4 lg:max-w-lg">
<div className="flex justify-between mb-3">
<h1>할 일 목록</h1>
</div>
<Lists todoData={todoData} setTodoData={setTodoData}/>
<Form handleSubmit={handleSubmit} inputValue={inputValue} setInputValue={setInputValue} />
</div>
</div>
);
}
export default App;
React.memo가 적용되지 않는다면, input 태그에 입력이 들어올 때 마다 inputValue가 변경되므로 부모 app 컴포넌트가 렌더링되어 모든 컴포넌트들이 리렌더링 되어진다.
React.memo 적용해 주면 실제 리렌더링이 필요한 app.js 와 From 컴포넌트만 바뀌는 것을 확인 할 수 있다.
[Lists.js]
import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
import List from "./List";
import React from"react"
function Lists({todoData, setTodoData}) {
console.log('Lists.js Rendering')
~~~~
return (
<div>
<List ~~/>
~~~~
</div>
);
}
export default React.memo(Lists)
[List.js]
import React, { useState } from 'react';
const List = React.memo(({ id, title, completed, todoData, setTodoData, provided, snapshot }) => {
console.log('List.js Rendering')
~~~~
return (
<div>
~~~~
/div>
)
});
export default List;
[Form.js]
export default function Form({handleSubmit, inputValue, setInputValue}) {
console.log('Form.js Rendering')
const handleChange = (e) => {
setInputValue(e.target.value)
}
return (
<div>
<form onSubmit={handleSubmit} className="flex pt-2 ">
<input
type="text"
name="value"
className="w-full px-3 py-2 mr-4 text-gray-500 border rounded shadow"
placeholder='해야 할 일을 입력하세요.'
value={inputValue}
onChange={handleChange}
/>
<input
type="submit"
value="입력"
className="p-2 text-blue-400 border-2 border-blue-400 rounded hover:text-white hover:bg-blue-200"
/>
</form>
</div>
);
}
실제 리렌더링이 필요한 app 과 Form 컴포넌트만 리렌더링 되는 것을 확인할 수 있다.