(React) useState 함수형 업데이트

호두파파·2021년 6월 9일
0

React

목록 보기
21/38

const onCreate = useCallback(() => {
  const user = {
    id: nextId.current, 
    height,
    weight
  }
  setUsers(users.concat(user));
  nextId.current += 1;
  setInputs({
    height: '',
    wight: ''
  });
}, [height, weight, users]);

const onChange = useCallback(e => {
  const { name, value } = e.target;
  setInputs({
    ...inputs,
    [name]:value
  })
}, [inputs]);

const onToggle = useCallback(id => {
  sestUsers(
    users.map(
      user => 
      	user.id === id
      		? { ...user, active: !user.active }
      		: user
    )
  );
}, [users]);

const onRemove = useCallback(id => {
  setUsers(users.filter(user => user.id !== id);
}, [users]);

위 코드는 각자 state의 변경이 일어나기 때문에, App.js의 자식 컴포넌트인 각종 js파일들이 만들어내는 컴포넌트가 리렌더링 되어져 버린다.

원하는 것만 리랜더링하려면, 다음과 같이 최적화해야한다.

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({
    height: '',
    weight: ''
  });

  const { height, weight } = inputs;
  const [users, setUsers] = useState([
    {
      id: 1,
      height: 185,
      weight: 75,
      active: false,
    },
    {
      id: 2,
      height: 167,
      weight: 50,
      active: false,
    },
    {
      id: 3,
      height: 173,
      weight: 80,
      active: false,
    }
  ]);

  const nextId = useRef(4);
  
  const onCreate = useCallback(() => {
    const user = {
      id: nextId.current,
      height, 
      weight
    }
    setUsers(users => users.concat(user));
    nextId.current += 1;
    setInputs({
      height: '',
      weight: ''
    });
  }, [height, weight]);
  
  const onChange = useCallback(e => {
    const { name, value } = e.target;
    setInputs(inputs => ({
      ...inputs, 
      [name]: value
    }));
  }, []);
  
  const onToggle = useCallback(id => {
    setUsers(users => 
      users.map(
      	user => 
          user.id === id
      		? { ...user, active: !user.active }
      		: user
      )
    );
  }, []);
  
  const onRemove = useCallback(id => {
    setUsers(users => users.filter(user => user.id !== id);
  }, []);
  
  const count = useMemo(() => countActiveUsers(users), [users]);
  return (
    <>
      <CreateUser
        height={height}
        weight={weight}
        onCreate={onCreate}
        onChange={onChange}
      />
      <UserList users={users} onToggle={onToggle} onRemove={onRemove} />
      <div>
        <b>활성 사용자 수 :</b>{count}
      </div>
    </>
  );
}

export default App;

이런 식으로 함수영 업데이트를 진행해주면 App이 바뀌어도, callback측에서는 []안에 바뀐 state들이 들어있지 않으므로, 리렌더링을 진행하지 않는다.

따라서, 리렌더링 횟수를 줄이기 위해서 함수형 업데이트를 하는 것이다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글