useMemo Hook

jini.choi·2022년 5월 20일
0

React

목록 보기
15/21
  • 이전에 연산된 값을 재사용. 주로 성능을 최적화할 때 사용

  • useMemo를 사용안하면 input값을 바꿀 때도 countActiveUsers함수가 호출되는 문제가 발생한다. 활성 사용자 수를 세는 건 users에 변화가 있을 때만 세야되는건데, input값이 바뀔때에도 컴포넌트가 리렌더링 되며 불필요할때에도 호출하여서 자원이 낭비된다.

  • 이러한 상황에는 useMemo를 사용하여 성능을 최적화한다.

  • Memo(memoized)는 이전에 계산한 값을 재사용 한다는 의미가 있다.

  • 이메일을 입력한다고 치면 CreateUser컴포넌트의 email이라는 속성(props)가 바뀌게 되는데 이 값은 원래 App컴포넌트의 state입니다. 결국 input에 입력하는 행위는 App Componentstate를 바꾸게 되는 행위.
    AppState가 변경됐으니 App Component가 다시 렌더링되면서 countActiveUsers가 실행되면서 호출

const count = useMemo(() => countActiveUsers(users), [users]);

첫번째 파라미터에는 어떻게 연산할지 정의하는 함수, 두번째는 deps배열을 넣어준다.
이 배열 안에 넣은 내용이 바뀌면, 우리가 등록한 함수를 호출해서 값을 연산해주고, 만약 내용이 바뀌지 않았다면 이전에 연산한 값을 재사용한다.

App.js

// import logo from './logo.svg';
// import './App.css';
import React, { useRef, useState, useMemo } from "react";
import CreateUser from "./CreateUser";
import UserList from "./UserList";

function countActiveUsers(users) {
  console.log('활성 사용자 수를 세는 중...');
  return users.filter(user => user.active).length;
};

function App() {
  const [inputs, setInputs] = useState({
    username: '',
    email: ''
  });
  const { username, email } = inputs;

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

  const [users, setUsers] = useState([
    {
        id: 1,
        username: 'jini',
        email: 'genie9105@gamail.com',
        active: true
    },
    {
        id: 2,
        username: 'biki',
        email: 'biki@gmail.com',
        active: false
    },
    {
        id: 3,
        username: 'nado',
        email: 'nado@gmail.com',
        active: false
    }
  ]);

  const nextId = useRef(4); //useref의 초기값은 4

  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email
    };
    // setUsers([...users, user]); 1번째 방법
    setUsers(users.concat(user)); //2번째 방법
    
    setInputs({
      username: '',
      email: ''
    });
    nextId.current += 1;
  };

  const onRemove = id => {
    // user.id가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
    // = user.id가 id 인 것을 제거함
    setUsers(users.filter(user => user.id !== id))
  };

  const onToggle = id => {
    setUsers(users.map(
      user => user.id === id
        ?{...user, active: !user.active}
        : user
    ));
  };

  const count = useMemo(() => countActiveUsers(users), [users]);

  return (
    <>
    <CreateUser 
      username={username} 
      email={email} 
      onChange={onChange} 
      onCreate ={onCreate}
    />
    <UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
    <div>활성 사용자 수 : {count}</div>
    </>
  );
}

export default App;

App안에 countActiveUsers 선언 시

const countActiveUsers = () => {
    console.log('count active users..');
    return users.filter(user => user.active).length;
}

UseList.js

import React from "react";

function User({ user, onRemove, onToggle }) {
    const { username, email, id, active } = user;

    return (
        <div>
            <b 
                style={{
                    color: active ? 'green' : 'black',
                    cursor: 'pointer'
                }}
                onClick={() => onToggle(id)}
            >
                {username}
            </b>
            &nbsp;
            <span>({email})</span>
            <button onClick={() => onRemove(id)}>삭제</button>
        </div>
    );
}
function UserList({ users, onRemove, onToggle }) {
    
    return (
        <div>
            {
                users.map(
                    user => (
                        <User 
                            user={user} 
                            key={user.id} 
                            onRemove={onRemove}
                            onToggle={onToggle}
                        />
                    )
                )    
            }
        </div>
    )
}

export default UserList;

CreateUser.js

import React from "react";

//onChange는 이 텍스트(input)값이 바뀌게 될때, onCreate는 버튼을 눌렀을 때 새로운 항목을 등록해주는 함수
function CreateUser({ username, email, onChange, onCreate }) {
    return (
        <div>
            <input
                name="username" 
                placeholder="계정명" 
                onChange={onChange} 
                value={username}
            />
            <input
                name="email" 
                placeholder="이메일" 
                onChange={onChange} 
                value={email}
            />
            <button onClick={onCreate}>등록</button>
        </div>
    );
}

export default CreateUser;


이 글은 패스트캠퍼스 '프론트엔드(React)올인원패키지Online'을 수강하며 정리한 노트입니다.
https://fastcampus.co.kr/search?keyword=%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C

profile
개발짜🏃‍♀️

0개의 댓글