useCallback, useMemo, memo

유석현(SeokHyun Yu)·2022년 11월 23일
0

React

목록 보기
15/21
post-thumbnail

AppMentorsButton.jsx

import React, { memo, useCallback, useMemo, useReducer } from "react";
import personReducer from "./person-reducer";

export default function AppMentorsButton() {
    const [person, dispatch] = useReducer(personReducer, initialPerson);

    // useCallback()은 함수의 참조값 자체를 캐싱
    // 컴포넌트가 호출될 때마다 초기화 되는 것을 방지
    const handleUpdate = useCallback(() => {
        const prev = prompt(`누구의 이름을 바꾸고 싶은가요?`);
        const current = prompt(`이름을 무엇으로 바꾸고 싶은가요?`);
        dispatch({ type: "updated", prev, current });
    }, []);

    const handleAdd = useCallback(() => {
        const name = prompt(`멘토의 이름은?`);
        const title = prompt(`멘토의 직함은?`);
        dispatch({ type: "added", name, title });
    }, []);

    const handleDelete = useCallback(() => {
        const name = prompt(`누구를 삭제하고 싶은가요?`);
        dispatch({ type: "deleted", name });
    }, []);

    return (
        <div>
            <h1>{person.name}</h1>
            <p>{person.name}의 앨범</p>
            <ul>
                {person.mentors.map((mentor, index) => (
                    <li key={index}>
                        {mentor.name} ({mentor.title})
                    </li>
                ))}
            </ul>
            <Button text="앨범 이름 변경" onClick={handleUpdate} />
            <Button text="앨범 삭재" onClick={handleDelete} />
            <Button text="앨범 추가" onClick={handleAdd} />
        </div>
    );
}

// Button은 AppMentorsButton이 리렌더링 될 때마다 같이 리렌더링됨
// 하지만 Button은 항상 같은 UI만 보여주는 정적인 요소라서 굳이 리렌더링 될 필요가 없음
// React.memo()는 이러한 정적인 컴포넌트를 렌더링 과정에서 재사용할 수 있게 해줌
// 예를 들어, 맨 처음 AppMentorsButton이 렌더링 될 때 Button 컴포넌트 3개도 같이 렌더링 되는데
// 이때의 Button 컴포넌트를 그대로 저장해놓고 props(text, onClick)의 상태가 변경되지 않는 이상
// AppMentorsButton이 리렌더링 될 때마다 재사용함
const Button = memo(({ text, onClick }) => {
    // useMemo()는 함수의 리턴값을 캐싱
    const result = useMemo(() => calculateSomething(), []);
    return (
        <button
            onClick={onClick}
            style={{
                backgroundColor: "black",
                color: "white",
                borderRadius: "20px",
                margin: "0.4rem",
            }}
        >
            {`${text} ${result}`}
        </button>
    );
});

function calculateSomething() {
    let total = 0;
    for (let i = 0; i < 10000; i++) {
        total += i;
    }
    return total;
}

const initialPerson = {
    name: "Kanye West",
    mentors: [
        {
            name: "Ye",
            title: "2018",
        },
        {
            name: "Jesus Is King",
            title: "2019",
        },
    ],
};
profile
Backend Engineer

0개의 댓글