Web Tech/react

react 기본 - 15.React.memo

걍가영 2021. 11. 30. 17:22

React.memo

props가 바뀌지 않았다면, 리렌더링을 방지하여 컴포넌트의 리렌더링 성능 최적화를 해줍니다.
클릭 및 체인지 같은 이벤트 함수들은 useCallback으로 재사용 해도 리렌더링을 막을 수 없습니다.

CreateUser.js

import React from 'react';

function CreateUser({username, email, onChange, onCreate}) {
    return (
        <>
            <input name="username" onChange={onChange} value={username} placeholder="계정명" type="text"/>
            <input name="email" onChange={onChange} value={email} placeholder="계정명" type="text"/>
            <button onClick={onCreate} type="submit">등록</button>
        </>
    )
}
// 내보낼 컴포넌트 React.memo로 감싸기
export default React.memo(CreateUser);


App.js

import React, {useRef, useState, useMemo, useCallback} from 'react';
import Inner from "./Inner";
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({
       usersname: '',
       email: ''
    });

    const {username, email} = inputs;

    const onChange = useCallback(e => {
            const {name,value} = e.target;
            setInputs({
                ...inputs,
                [name]: value
            });
        }, []);
	// 함수형 업데이트 진행하게되면,
	// 콜백함수의 파라미터에서 최신 users를 참조할 수 있음
    const [users, setUsers] = useState ([
        {
            id: 1,
            username: 'a',
            email : 'aaa@gmail.com',
            active: true
        },
        {
            id: 2,
            username: 'b',
            email : 'bbb@gmail.com',
            active: false
        },
        {
            id: 3,
            username: 'c',
            email : 'ccc@gmail.com',
            active: false
        }
    ]);
    const nextId = useRef(4);

    const onCreate = useCallback(() => {
        const user = {
            id: nextId.current,
            username,
            email
        }
        setUsers([...users, user]);
        setInputs({
           username: '',
           email: ''
        });
        nextId.current += 1;
	// 함수형 업데이트 -> deps users 제거
    },[username, email]);

    const onRemove = useCallback(
        id => {
            setUsers(users.filter(user => user.id !== id));
	// 함수형 업데이트 -> deps users 제거
        }, []);

    const onToggle = useCallback(
        id => {
            setUsers(
                users.map(user => user.id === id ? {...user, active: !user.active} : user )
            )
	// 함수형 업데이트 -> deps users 제거
        }, []);
    
    const count = useMemo(() => countActiveUsers(users), [users]);

    return (
        <React.Fragment>
            <Inner>
                <CreateUser
                    username={username}
                    email={email}
                    onChange={onChange}
                    onCreate={onCreate}
                />
                <UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
                // 렌더링 할 때 보여줌
                <p>활성사용자 수 : {count}</p>
            </Inner>
        </React.Fragment>
    );
}

export default App;