Action
: ๋น๋๊ธฐ ์ ํ์ ์ฌ์ฉํ๋ ํจ์
(Before) Example1. passive process
function OrderCoffee({}) {
const [coffee, setCoffee] = useState("");
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async () => {
setIsPending(true);
const error = await orderCoffee(coffee);
setIsPending(false);
if (error) {
setError(error);
return;
}
redirect("/order-success");
};
return (
<div>
<input value={coffee} onChange={(event) => setCoffee(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Order Coffee
</button>
{error && <p>{error}</p>}
</div>
);
}
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ , ์ด์ ๋์ํ์ฌ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ ๋, ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ์ด๋ฆ์ ๋ณ๊ฒฝํ๋ ์์์ ์ ์ถํ ๋ API ์์ฒญ์ ์ํํ ํ ์๋ต์ ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ ๊ณผ๊ฑฐ์๋ ๋ณด๋ฅ ์ํ, ์ค๋ฅ, ๋๊ด์ ์ ๋ฐ์ดํธ, ์์ฐจ์ ์์ฒญ ๋ฑ์ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ์ต๋๋ค.
(react-19) Example2. async transition
// Using pending state from Actions
function OrderCoffee({}) {
const [coffee, setCoffee] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
const error = await orderCoffee(coffee);
if (error) {
setError(error);
return;
}
redirect("/order-success");
})
};
return (
<div>
<input value={coffee} onChange={(event) => setCoffee(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Order Coffee
</button>
{error && <p>{error}</p>}
</div>
);
}
async transition์ ์ฆ์ isPending ์ํ๋ฅผ true๋ก ์ค์ ํ๊ณ , ๋น๋๊ธฐ ์์ฒญ์ ์ํํ ํ, ๋ชจ๋ ์ ํ์ด ๋๋๋ฉด isPending์ false๋ก ์ ํํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ ๋์ ํ์ฌ UI๋ฅผ responsive and interactiveํ ์ ์๊ฒ ๋ง๋ค์ด์ค๋๋ค.
`useTransition`์ React์ ๋์์ฑ ๋ชจ๋๋ฅผ ํ์ฉํ์ฌ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ธฐ๋ฅ์ผ๋ก, ๋ด๋ถ์ ์ผ๋ก React์ ์ค์ผ์ค๋ฌ์ Fiber ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ์ฐ์ ์์๋ฅผ ๊ด๋ฆฌํ๊ณ , ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ฐจ๋จ๋์ง ์๋๋ก ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ ๋ฐ์์ฑ์ ์ ์งํ๋ฉด์ ๋ณต์กํ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
(react-19) Example3. useActionState
// Using <form> Actions and useActionState
function OrderCoffee({ coffee, setCoffee }) {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await orderCoffee(formData.get("coffee"));
if (error) {
return error;
}
redirect("/order-success");
return null;
},
null,
);
return (
<form action={submitAction}>
<input type="text" name="coffee" />
<button type="submit" disabled={isPending}>Order Coffee</button>
{error && <p>{error}</p>}
</form>
);
}
์ก์ (Actions)์ ๊ธฐ๋ฐ์ผ๋ก, ๋ฆฌ์กํธ 19๋ ์ผ๋ฐ์ ์ธ ์ก์ ์ผ์ด์ค๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ก์ด ํ React.useActionState๋ฅผ ๋์ ํ์ต๋๋ค. ์ก์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ถํ๋ ์์ ์ ์๋์ผ๋ก ๊ด๋ฆฌํด ์ค๋๋ค.
useActionState๋ ํจ์(“์ก์ ”)๋ฅผ ์ธ์๋ก ๋ฐ์, ํธ์ถํ ๋ํ๋ ์ก์ ์ ๋ฐํํฉ๋๋ค. ์ด๋ ์ก์ ๋ค์ด ์กฐํฉ๋๊ธฐ ๋๋ฌธ์ ์๋ํฉ๋๋ค. ๋ํ๋ ์ก์ ์ด ํธ์ถ๋๋ฉด, useActionState๋ ์ก์ ์ ๋ง์ง๋ง ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ดํฐ๋ก ๋ฐํํ๊ณ , ์ก์ ์ ๋ณด๋ฅ ์ํ๋ฅผ ๋ณด๋ฅ๋ก ๋ฐํํฉ๋๋ค.
(react-19) Example4. ์ค์ ์ฌ์ฉ ์์
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
if (!formData) {
setCoffeeImage(null);
return null;
}
const coffeeName = formData.get("coffee");
const shot = formData.get("shot");
const temperature = formData.get("temperature");
const coffeeSrc = await orderCoffee(coffeeName, temperature, shot);
if (!coffeeSrc) {
return "Failed to fetch coffee image";
}
setCoffeeImage(coffeeSrc);
return null;
},
null,
);
์ฐธ๊ณ
React.useActionState๋ ์ด์ ์๋ canary release ์์ ReactDOM.useFormState๋ผ๊ณ ๋ถ๋ ธ์ผ๋, ์ด๋ฆ์ด ๋ณ๊ฒฝ๋์๊ณ useFormState๋ ํ๊ธฐ๋์์ต๋๋ค.
'๐ Front > โ๏ธ React JS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Next.js 15 instrumentation์ด ํ๋ก๋์ ์์ ์๋์๊ฐ๋ค๋ฉด (0) | 2025.06.20 |
|---|---|
| Tailwind v4 ๋์ ํ๋ค๊ฐ monorepo ๋น๋ ์์คํ ์ ๋ฏ์ด๊ณ ์น ์ฐ (2) | 2025.06.01 |
| [React] ๊น๋นก์ ํ์ ํด๊ฒฐ (useLayoutEffect, APIํธ์ถ) (0) | 2022.03.30 |
| virtual DOM ํํค์น๊ธฐ (0) | 2021.12.09 |
| React [๋ฆฌ๋ ๋๋ง ๊ณผ์ ] (0) | 2021.09.08 |