React의 새로운 버전인 18버전은 사실 release 된지는 두달정도 되었지만 (3월 29일에 release 됨) 유튜브 알고리즘을 타고 여기저기 흘러다니던 중,
한 영상을 보고 '오.. 새로운 hook이 추가되었구나.. 뭔지 찾아나 볼까' 하고 관련 문서를 찾아봤고 그중 몇가지만 골라서 이렇게 포스트로 정리하게 되었다.
const [isPending, startTransition] = useTransition();
useTransition의 기본적인 사용법은 위와 같다.
React 공식 문서에 적혀있는 설명을 간략하게 설명해보면
useTransition은 일부 state의 업데이트를 미룰수 있게, 즉 급하지 않은 것으로 여기도록 해준다.
예시 코드와 함께 좀더 자세하게 알아보자.
const arr = new Array(10000).fill(0);
export default function App() {
const [str, setStr] = useState("");
const [isPending, startTransition] = useTransition();
const onChangeInput = (e) => {
setStr(e.target.value);
};
return (
<div className="App">
<input onChange={onChangeInput}/>
{
arr.map(()=> {
return <div>{str}</div>
})
}
</div>
);
}
예제 코드를 보면 input
을 통해 state
를 입력받고 업데이트 하며 해당 state
를 10000번 출력하도록 하고 있다.
이런 코드가 있을 때 input을 통해 state를 업데이트 하게 되면 입력을 받을 때 마다 state가 업데이트 되어 10000개의 div가 리렌더링 되기 때문에 엄청난 저하가 발생하게 된다.
const onChangeInput = (e) => {
startTransition(() => setStr(e.target.value));
};
저하를 발생시키는 setState 부분을 startTransition으로 묶어주면 기존의 코드보다는 저하가 덜하다는 것을 확인 할 수 있다.
isPending은 해당 요소가 미뤄지고 있는 지 여부를 boolean 값으로 return 한다.
만약 isPending이 필요 없다면 아래와 같이 startTransition만 불러와서 사용도 가능하다!
import { startTransition } from 'react';
const deferredValue = useDeferredValue(value);
useDeferredValue의 기본적인 사용법은 위와 같다.
useDeferredValue은 급하지 않은 트리 부분의 re-rendering 을 연기하는 역할을 한다.
import { useDeferredValue, useState } from "react";
const SlowUI = () => (
<>
{Array(50000)
.fill(1)
.map((_, index) => (
<span key={index}>{100000} </span>
))}
</>
);
function App() {
const [value, setValue] = useState(0);
const deferredValue = useDeferredValue(value);
const handleClick = () => {
setValue(value + 1);
};
return (
<>
<button onClick={handleClick}>{value}</button>
<div>DeferredValue: {deferredValue}</div>
<div>
<SlowUI />
</div>
</>
);
}
export default App;
버튼을 누르게 되면 일정 시간 지연이 된 후에 (급하지 않은 부분이라고 여겨지고 있기 때문에) 값이 바뀌는 것을 확인 할 수 있다.
const id = useId();
useId의 기본적인 사용법은 위와 같다.
useId는 고유한 id 값을 생성해주는 hook 이다.
웹 개발을 하다보면 element에 고유한 id 값을 지정해줘야 하는 경우들이 있는데 그럴 때 사용 할 수 있는 hook이다.
Child.js
import "./styles.css";
import { useId } from "react";
export default function Child() {
const id = useId();
return (
<div className="child">
<div>
<p>child id : {id}</p>
</div>
</div>
);
}
App.js
import "./styles.css";
import { useId } from "react";
import Child from "./Child";
export default function App() {
const id = useId();
return (
<div className="App">
<div>
<p>first id : {id}</p>
<Child />
<Child />
<Child />
<Child />
<Child />
<Child />
</div>
</div>
);
}
위와 같은 코드가 있다고 하면 아래와 같이 고유한 id값을 출력하게 된다.
useInsertionEffect(() => {
// do something
});
useInsertionEffect의 기본적인 사용법은 위와 같다.
useInsertionEffect는 css-in-js 라이브러리가 rendering 도중에 스타일을 삽입할 때 발생하는 성능 문제를 해결한다.
import { useEffect, useInsertionEffect, useLayoutEffect } from 'react';
const Child = () => {
useEffect(() => {
console.log('useEffect child is called');
});
useLayoutEffect(() => {
console.log('useLayoutEffect child is called');
});
useInsertionEffect(() => {
console.log('useInsertionEffect child is called');
});
};
function App() {
useEffect(() => {
console.log('useEffect app is called');
});
useLayoutEffect(() => {
console.log('useLayoutEffect app is called');
});
useInsertionEffect(() => {
console.log('useInsertionEffect app is called');
});
return (
<div className="App">
<Child />
<p>Random Text</p>
</div>
);
}
export default App;
위 코드를 통해 실행 순서를 확인 할 수 있는데 그 순서는 다음과 같다.
useInsertionEffect -> useLayoutEffect -> useEffect
이 hook은 사실상 styled-components를 위해서 나왔다 해도 무방하다고 하는데.. 실제로 사용해봐야 정확히 무슨 역할을 하는지 알 수 있을 것 같다.