✔️ React 훅 더 공부하기
유튜버 코딩애플님과 별코딩님의 강의들을 보고 요약한 나의 일지
예 )
import { useState, useTransition, useDeferredValue } from "react";
let a = new Array(10000).fill(0);
export default function App() {
let [name, setName] = useState("");
let [isPending, startTransition] = useTransition();
let state = useDeferredValue(name);
return (
<div className="App">
<input
onChange={(e) => {
startTransition(() => {
setName(e.target.value);
});
}}
/>
{isPending
? "로딩중"
: a.map(() => {
return <div>{state}</div>;
})}
</div>
);
}
위의 코드는 input 이 작성할 때, 배열이 10000번 동작시키는 코드이다.
정확히는 완성된 코드이다.
아까 말했듯이 useTransition 은 state 의 변경 함수에 성능 저하가 일으키면 사용한다.
모양은 useState 와 비슷한데, 첫 번째 인자로는 isPending, 그리고 두 번째는 startTransition 라는 인자를 받는다.
isPending 은 startTransition 이 처리중일 때 true 로 변한다.
startTransition 은 함수이고 콜백을 사용해서 동작할 코드를 늦게 처리하게 해준다.
늦게 처리한다는 의미는 렌더링이 될 때, 먼저 실행되는게 있고 그 후에는 useTransition 의 사용한 코드가 작동한다.
그리고 useDeferredValue 는 useTransition 을 써도 느리다고 생각되면, 사용하는 기능이다.
작동방식은 안에 있는 state 에 변동사항이 생기면 늦게 처리해준다.
예 )
import { useMemo, useState } from "react";
import Child from "./Child";
export default function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log("부모 컴포넌트가 렌더링 되었어요");
const name = useMemo(() => {
return {
lastName: "홍",
firstName: "길동"
};
}, []);
return (
<div style={{ border: "2px solid navy", padding: "10px" }}>
<h1>💑부모</h1>
<p>age : {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={name} />
</div>
);
}
import { memo } from "react";
function Child({ name }) {
console.log("자녀 컴포넌트도 렌더링 되었네요");
return (
<div style={{ border: "4px solid powderblue", padding: "35px" }}>
<h3>👶자녀</h3>
<p>성: {name.lastName}</p>
<p>이름: {name.firstName}</p>
</div>
);
}
export default memo(Child);
이번에는 React.memo 와 useMemo 를 활용한 코딩이다.
React.memo 는 useMemo, useCallback 와 마찬가지로, 컴포넌트를 최적화 시키는 기법이다.
React.memo를 통해 불필요한 렌더링을 방지해서 앱의 성능을 향상시킬 수 있다.
React.memo 는 리액트에서 제공하는 고차 컴포넌트(HOC)이다.
최적화가 된 컴포넌트는 렌더링되어야 할 상황일 때마다, prop check 를 통해 자신이 받는 props 에 변화가 있는 없는지 확인한다.
Props 에 변화가 있다면?
Props 에 변화가 없다면?
React.memo 에서 memo 는 Memoization 을 뜻한다.
Memoization 이란 이미 계산한 값을 메모리 상에 저장하고 필요할 때마다 꺼내서 재사용하는 기법이다.
하지만 완벽하게 보여도, 무분별한 사용은 독이 될 수 있다.
그 이유는 컴포넌트를 메모이징 할 때 렌더링 된 결과를 어딘가에 저장해야 하기 때문에 메모리를 추가적으로 소비한다.
React.memo 는 오직 Props 변화에만 의존하는 최적화 방법이다. (중요!)
만약 컴포넌트가 useState, useReducer 그리고 useContext 와 같은 상태 관련 훅을 사용한다면, props 에 변화가 없더라도 여전히 state 와 context 가 변할때마다 다시 렌더링이 된다.
자바스크립트에서 객체는 문자열과 숫자형 같은 원시 타입들과 달리 변수 안에 그대로 저장되는게 아니라, 해당 객체가 저장되어있는 메모리의 주소가 변수안에 저장된다. (ex: #1111)
렌더링이 될 때마다, 객체 안에 있는 메모리의 주소가 바뀐다!
예 )
import { useState, useCallback } from "react";
import Child from "./Child";
export default function App() {
const [parentAge, setParentAge] = useState(0);
const incrementParentAge = () => {
setParentAge(parentAge + 1);
};
console.log("부모 컴포넌트가 렌더링 되었어요");
const tellMe = useCallback(() => {
console.log("길동아 사랑해 ❤");
}, []);
return (
<div style={{ border: "2px solid navy", padding: "10px" }}>
<h1>💑부모</h1>
<p>age : {parentAge}</p>
<button onClick={incrementParentAge}>부모 나이 증가</button>
<Child name={"홍길동"} tellMe={tellMe} />
</div>
);
}
import { memo } from "react";
function Child({ name, tellMe }) {
console.log("자녀 컴포넌트도 렌더링 되었네요");
return (
<div style={{ border: "4px solid powderblue", padding: "35px" }}>
<h3>👶자녀</h3>
<p>이름: {name}</p>
<button onClick={tellMe}>엄마 나 사랑해?</button>
</div>
);
}
export default memo(Child);
이번에는 React.memo 와 useCallback 훅을 활용한 코딩이다.
위에 코드는 2번째에서 본 코딩과 흡사하지만, 이번에는 함수를 메모이징하는 것이다!
useCallback 은 어떠한 함수를 메모이징하기 위해서 사용한다.
반면에, useMemo 는...
useMemo 는 어떠한 값을 메모이징하기 위해서 사용한다.