[사용 예시]
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = React.useRef();
React.useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
}));
return <input ref={inputRef} />;
});
function Parent() {
const ref = React.useRef();
return (
<div>
<FancyInput ref={ref} />
<button onClick={() => ref.current.focus()}>포커스</button>
</div>
);
}
[사용 시기]
DOM 요소의 위치, 크기 조정이 필요할 때.
애니메이션 효과나 스크롤 위치 설정.
[차이점]
useEffect: 렌더링 이후 실행 (비동기).
useLayoutEffect: 렌더링 직전에 실행 (동기).
function LayoutEffectExample() {
const divRef = React.useRef();
React.useLayoutEffect(() => {
console.log(divRef.current.offsetHeight);
}, []);
return <div ref={divRef}>레이아웃 확인</div>;
}
function App() {
const [isPending, startTransition] = React.useTransition();
const [count, setCount] = React.useState(0);
const handleClick = () => {
startTransition(() => {
setCount((c) => c + 1);
});
};
return (
<div>
<button onClick={handleClick}>클릭</button>
{isPending ? <p>로딩 중...</p> : <p>결과: {count}</p>}
</div>
);
}
function Component() {
const id = React.useId();
return (
<label htmlFor={id}>
입력창
<input id={id} />
</label>
);
}
function App({ value }) {
const deferredValue = React.useDeferredValue(value);
return <div>{deferredValue}</div>;
}
"use client";
function App() {
const [state, submitAction, isPending] = useActionState(customAction, initialState); // initialState like {error: null}
return (
<form action={submitAction}>
<button disabled={isPending}></button>
{state.error && <span>error</span>}
</form>
)
}
리액트 훅이므로 클라이언트 컴포넌트에서 사용해야 한다. pending 상태와 useState, onSubmit 함수를 축약해 개인적으로 가독성과 데이터 응집도가 높아졌다고 생각한다.
“form, input, button 요소에 action 및 formAction props로 Server Action을 전달하면 JavaScript가 비활성화되었거나 코드가 로드되기 전에도 사용자가 폼을 제출하고, 오류를 표시할 수 있게 되었다.”
JavaScript가 비활성화되거나 코드가 로드되기 전에 사용자가 form을 제출할 수 있으면 뭐가 좋은걸까?
사용자의 인터넷 연결이 느리거나, 장치 성능이 낮거나, JavaScript가 비활성화된 환경에서도 폼 제출 기능이 정상적으로 작동하도록 보장해줄 수 있다. 이로써 웹사이트의 접근성을 높여 모든 사용자에게 일관된 경험을 제공할 수 있게 되고, 결과적으로 사용자가 겪을 수 있는 잠재적인 문제를 줄이고 더 많은 사용자가 서비스를 이용할 수 있게 하는 것이다.