-
컴포넌트 성능 최적화(함수형 업데이트, 리덕스)프론트엔드 2022. 8. 18. 14:50
컴포넌트가 리렌더링하는 순간
1. 자신이 전달받은 props가 변경될 때
2. 자신의 stat가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. forceUpdate 함수가 실행될 때컴포넌트 2000개가 리렌더링 된다면? 앱의 성능이 급격히 저하된다.
따라서 컴포넌트 리렌더링 성능을 최적화해줄 필요가 있다.
1. React.memo : 컴포넌트의 props가 바뀌지 않았다면, 리렌더링을 하지 않도록 한다.
const TodoList = ({ todos, onRemove }) => {return (<TodoListdesign>{todos.map((todo) => (<TodoListItemtodo={todo}key={todo.user_key}onRemove={onRemove}></TodoListItem>))}</TodoListdesign>);};
export default React.memo(TodoList); 컴포넌트를 만들고 감싸주기만 하면 된다.2. useState의 함수형 업데이트 : 함수가 계속 만들어지는 상황을 방지한다.
const onInsert = useCallback((content, createdDate) => {const todo = {id: nextId.current,content, //백엔드에서 받아온 데이터 이름createdDate, //백엔드에서 받아온 데이터 이름};setTodos(todos.concat(todo)); //todos라는 배열에 생성된 todo 삽입 이 부분을 바꾼다.nextId.current += 1;},[todos] 이 부분을 바꾼다.);
const onRemove = useCallback((id) => {setTodos(todos.filter((todo) => todo.id !== id)); 이 부분을 바꾼다.},[todos] 이 부분을 바꾼다.);const onInsert = useCallback((content, createdDate) => {const todo = {id: nextId.current,content, //백엔드에서 받아온 데이터 이름createdDate, //백엔드에서 받아온 데이터 이름};setTodos(todos => todos.concat(todo)); //todos라는 배열에 생성된 todo 삽입nextId.current += 1;},[]);
const onRemove = useCallback((id) => {setTodos(todos => todos.filter((todo) => todo.id !== id));},[]);새로운 상태를 바로 파라미터로 넣는 대신, 상태 업데이트를 어떻게 업데이트할지 정의해주는 것이다. 그러면 useCallback 을 사용할 때 두번째 파라미터로 넣는 배열에 []처리해도 된다.
3. useReducer : useState 함수형 업데이트를 사용하는 대신, 리듀서를 사용해도 함수가 계속 만들어지는 현상을 막을 수 있다.
function todoReducer(todos, action) {switch (action.type) {case "INSERT":return todos.concat(action.todo); useState의 함수형 업데이트 사용case "REMOVE":return todos.filter((todo) => todo.id !== action.id);case "Toggle":return todos.map((todo) =>todo.id === action.id ? { ...todo, checked: !todo.checked } : todo);default:return todos;}}
const App = () => {const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos); 3번째 파라미터에 초기값을 넣어줬다.
두번째에 undefined를 쓰고 세번째에 초기값을 넣어주면 맨 처음 렌더링될 때만 createBulkTodos함수가 호출된다.
const nextId = useRef(4);const onInsert = useCallback((content, createdDate) => {const todo = {id: nextId.current,content,createdDate,checked: false,};
dispatch({ type: "INSERT", todo }); 두번째 파라미터는 전달인자이다.nextId.current += 1;}, []);
const onRemove = useCallback((id) => {dispatch({ type: "REMOVE", id });}, []);
const onToggle = useCallback((id) => {dispatch({ type: "TOGGLE", id });}, []);
return (<TodoTemplate><TodoInsert onInsert={onInsert}></TodoInsert><TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} ></TodoList>
</TodoTemplate>);};
export default App;우리는 위코드를 보며 불변성을 유지하면서 상태를 업데이트하는 것이 왜 중요한지 배웠다. (성능 최적화)
4. immer을 사용하지 않고 불변성 유지
...이어서
'프론트엔드' 카테고리의 다른 글
WebSoket(stompJS + React) (0) 2023.01.18 케이커 웹/앱 - 5 (제안서) (0) 2022.08.15 케이커 웹/앱 - 4 (파일 업로드, 드래그 앤 드롭) (0) 2022.08.14 케이커 웹/앱 - 3 (사이드바) (0) 2022.08.14 케이커 웹/앱 - 2 (마이페이지) (1) 2022.08.14