Reactμ useActionStateλ₯Ό μν λ¨Έμ κ³Ό ν¨κ» μ¬μ©νμ¬ κ²¬κ³ νκ³ μμΈ‘ κ°λ₯ν μ¬μ©μ μΈν°νμ΄μ€λ₯Ό ꡬμΆνμΈμ. 볡μ‘ν μ ν리μΌμ΄μ μ μν μ‘μ μν μ ν λ‘μ§μ λ°°μ보μΈμ.
React useActionState μν λ¨Έμ : μ‘μ μν μ ν λ‘μ§ λ§μ€ν°νκΈ°
Reactμ useActionState
λ λΉλκΈ° μν μ
λ°μ΄νΈλ₯Ό λ¨μννκΈ° μν΄ μ€κ³λ κ°λ ₯ν ν
μΌλ‘, React 19(νμ¬ μΉ΄λ리 λ²μ )μ λμ
λμμ΅λλ€. νΉν μλ² μ‘μ
μ λ€λ£° λ μ μ©ν©λλ€. μν λ¨Έμ κ³Ό κ²°ν©νλ©΄ 볡μ‘ν UI μνΈμμ©κ³Ό μν μ νμ μ°μνκ³ κ²¬κ³ νκ² κ΄λ¦¬ν μ μλ λ°©λ²μ μ 곡ν©λλ€. μ΄ λΈλ‘κ·Έ κ²μλ¬Όμμλ useActionState
λ₯Ό μν λ¨Έμ κ³Ό ν¨κ» ν¨κ³Όμ μΌλ‘ νμ©νμ¬ μμΈ‘ κ°λ₯νκ³ μ μ§λ³΄μνκΈ° μ¬μ΄ React μ ν리μΌμ΄μ
μ ꡬμΆνλ λ°©λ²μ μμΈν μ΄ν΄λ³΄κ² μ΅λλ€.
μν λ¨Έμ μ΄λ 무μμΈκ°?
μν λ¨Έμ μ μμ€ν μ λμμ μ νν μμ μνμ κ·Έ μνλ€ κ°μ μ νμΌλ‘ μ€λͺ νλ κ³μ°μ μνμ λͺ¨λΈμ λλ€. κ° μνλ μμ€ν μ κ³ μ ν 쑰건μ λνλ΄λ©°, μ νμ μμ€ν μ΄ ν μνμμ λ€λ₯Έ μνλ‘ μ΄λνκ² νλ μ΄λ²€νΈλ₯Ό λνλ λλ€. μμλμ λΉμ·νμ§λ§ λ¨κ³ κ° μ΄λ λ°©λ²μ λν΄ λ μ격ν κ·μΉμ κ°μ§λ€κ³ μκ°ν μ μμ΅λλ€.
React μ ν리μΌμ΄μ μμ μν λ¨Έμ μ μ¬μ©νλ©΄ λ€μκ³Ό κ°μ μ¬λ¬ μ΄μ μ μ»μ μ μμ΅λλ€:
- μμΈ‘ κ°λ₯μ±: μν λ¨Έμ μ λͺ ννκ³ μμΈ‘ κ°λ₯ν μ μ΄ νλ¦μ κ°μ νμ¬ μ ν리μΌμ΄μ μ λμμ λ μ½κ² μΆλ‘ ν μ μκ² ν©λλ€.
- μ μ§λ³΄μμ±: μν λ‘μ§μ UI λ λλ§κ³Ό λΆλ¦¬ν¨μΌλ‘μ¨ μν λ¨Έμ μ μ½λ ꡬμ±μ κ°μ νκ³ μ ν리μΌμ΄μ μ μ μ§λ³΄μ λ° μ λ°μ΄νΈλ₯Ό λ μ½κ² λ§λλλ€.
- ν μ€νΈ μ©μ΄μ±: κ° μνμ μ νμ λν μμ λμμ μ½κ² μ μν μ μκΈ° λλ¬Έμ μν λ¨Έμ μ λ³Έμ§μ μΌλ‘ ν μ€νΈνκΈ° μ½μ΅λλ€.
- μκ°μ νν: μν λ¨Έμ μ μκ°μ μΌλ‘ ννλ μ μμ΄ λ€λ₯Έ κ°λ°μλ μ΄ν΄κ΄κ³μμκ² μ ν리μΌμ΄μ μ λμμ μ λ¬νλ λ° λμμ΄ λ©λλ€.
useActionState
μκ°
useActionState
ν
μ μ¬μ©νλ©΄ μ μ¬μ μΌλ‘ μ ν리μΌμ΄μ
μνλ₯Ό λ³κ²½νλ μ‘μ
μ κ²°κ³Όλ₯Ό μ²λ¦¬ν μ μμ΅λλ€. μλ² μ‘μ
κ³Ό μννκ² μλνλλ‘ μ€κ³λμμ§λ§, ν΄λΌμ΄μΈνΈ μΈ‘ μ‘μ
μλ μ μ©ν μ μμ΅λλ€. λ‘λ© μν, μ€λ₯, μ‘μ
μ μ΅μ’
κ²°κ³Όλ₯Ό κ΄λ¦¬νλ κΉλν λ°©λ²μ μ 곡νμ¬ λ°μμ±μ΄ λ°μ΄λκ³ μ¬μ©μ μΉνμ μΈ UIλ₯Ό λ μ½κ² ꡬμΆν μ μκ² ν΄μ€λλ€.
λ€μμ useActionState
κ° μ¬μ©λλ κΈ°λ³Έ μμ μ
λλ€:
const [state, dispatch] = useActionState(async (prevState, formData) => {
// μ¬κΈ°μ μ‘μ
λ‘μ§μ μμ±ν©λλ€
try {
const result = await someAsyncFunction(formData);
return { ...prevState, data: result };
} catch (error) {
return { ...prevState, error: error.message };
}
}, { data: null, error: null });
μ΄ μμ μμ:
- 첫 λ²μ§Έ μΈμλ μ‘μ μ μννλ λΉλκΈ° ν¨μμ λλ€. μ΄μ μνμ νΌ λ°μ΄ν°(ν΄λΉνλ κ²½μ°)λ₯Ό λ°μ΅λλ€.
- λ λ²μ§Έ μΈμλ μ΄κΈ° μνμ λλ€.
- μ΄ ν μ νμ¬ μνμ λμ€ν¨μΉ ν¨μλ₯Ό ν¬ν¨νλ λ°°μ΄μ λ°νν©λλ€.
useActionState
μ μν λ¨Έμ κ²°ν©νκΈ°
μ§μ ν κ°λ ₯ν¨μ useActionState
λ₯Ό μν λ¨Έμ κ³Ό κ²°ν©ν λ λνλ©λλ€. μ΄λ₯Ό ν΅ν΄ λΉλκΈ° μ‘μ
μ μν΄ νΈλ¦¬κ±°λλ 볡μ‘ν μν μ νμ μ μν μ μμ΅λλ€. κ°λ¨ν μ μμκ±°λ μ»΄ν¬λνΈκ° μ ν μΈλΆ μ 보λ₯Ό κ°μ Έμ€λ μλ리μ€λ₯Ό μκ°ν΄ λ³΄κ² μ΅λλ€.
μμ : μ ν μμΈ μ 보 κ°μ Έμ€κΈ°
μ ν μμΈ μ 보 μ»΄ν¬λνΈλ₯Ό μν΄ λ€μκ³Ό κ°μ μνλ₯Ό μ μνκ² μ΅λλ€:
- Idle(μ ν΄): μ΄κΈ° μν. μμ§ μ ν μμΈ μ 보λ₯Ό κ°μ Έμ€μ§ μμμ΅λλ€.
- Loading(λ‘λ© μ€): μ ν μμΈ μ 보λ₯Ό κ°μ Έμ€λ μ€μΈ μνμ λλ€.
- Success(μ±κ³΅): μ ν μμΈ μ 보λ₯Ό μ±κ³΅μ μΌλ‘ κ°μ Έμ¨ νμ μνμ λλ€.
- Error(μ€λ₯): μ ν μμΈ μ 보λ₯Ό κ°μ Έμ€λ μ€ μ€λ₯κ° λ°μν κ²½μ°μ μνμ λλ€.
μ΄ μν λ¨Έμ μ κ°μ²΄λ₯Ό μ¬μ©νμ¬ ννν μ μμ΅λλ€:
const productDetailsMachine = {
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loading',
},
},
loading: {
on: {
SUCCESS: 'success',
ERROR: 'error',
},
},
success: {
type: 'final',
},
error: {
on: {
FETCH: 'loading',
},
},
},
};
μ΄κ²μ λ¨μνλ ννμ λλ€. XStateμ κ°μ λΌμ΄λΈλ¬λ¦¬λ κ³μΈ΅μ μν, λ³λ ¬ μν, κ°λμ κ°μ κΈ°λ₯μ κ°μΆ λ μ κ΅ν μν λ¨Έμ ꡬνμ μ 곡ν©λλ€.
React ꡬν
μ΄μ μ΄ μν λ¨Έμ μ React μ»΄ν¬λνΈμμ useActionState
μ ν΅ν©ν΄ λ³΄κ² μ΅λλ€.
import React from 'react';
// μμ ν μν λ¨Έμ κ²½νμ μνλ€λ©΄ XStateλ₯Ό μ€μΉνμΈμ. μ΄ κΈ°λ³Έ μμ μμλ κ°λ¨ν κ°μ²΄λ₯Ό μ¬μ©ν©λλ€.
// import { createMachine, useMachine } from 'xstate';
const productDetailsMachine = {
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loading',
},
},
loading: {
on: {
SUCCESS: 'success',
ERROR: 'error',
},
},
success: {
type: 'final',
},
error: {
on: {
FETCH: 'loading',
},
},
},
};
function ProductDetails({ productId }) {
const [state, dispatch] = React.useReducer(
(state, event) => {
const nextState = productDetailsMachine.states[state].on[event];
return nextState || state; // μ νμ΄ μ μλμ§ μμ κ²½μ° λ€μ μν λλ νμ¬ μν λ°ν
},
productDetailsMachine.initial
);
const [productData, setProductData] = React.useState(null);
const [error, setError] = React.useState(null);
React.useEffect(() => {
if (state === 'loading') {
const fetchData = async () => {
try {
const response = await fetch(`https://api.example.com/products/${productId}`); // μ¬λ¬λΆμ API μλν¬μΈνΈλ‘ κ΅μ²΄νμΈμ
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setProductData(data);
setError(null);
dispatch('SUCCESS');
} catch (e) {
setError(e.message);
setProductData(null);
dispatch('ERROR');
}
};
fetchData();
}
}, [state, productId, dispatch]);
const handleFetch = () => {
dispatch('FETCH');
};
return (
μ ν μμΈ μ 보
{state === 'idle' && }
{state === 'loading' && λ‘λ© μ€...
}
{state === 'success' && (
{productData.name}
{productData.description}
κ°κ²©: ${productData.price}
)}
{state === 'error' && μ€λ₯: {error}
}
);
}
export default ProductDetails;
μ€λͺ :
productDetailsMachine
μ μν λ¨Έμ μ λνλ΄λ κ°λ¨ν μλ°μ€ν¬λ¦½νΈ κ°μ²΄λ‘ μ μν©λλ€.React.useReducer
λ₯Ό μ¬μ©νμ¬ λ¨Έμ μ κΈ°λ°μΌλ‘ μν μ νμ κ΄λ¦¬ν©λλ€.- Reactμ
useEffect
ν μ μ¬μ©νμ¬ μνκ° 'loading'μΌ λ λ°μ΄ν° κ°μ Έμ€κΈ°λ₯Ό νΈλ¦¬κ±°ν©λλ€. handleFetch
ν¨μλ 'FETCH' μ΄λ²€νΈλ₯Ό λμ€ν¨μΉνμ¬ λ‘λ© μνλ₯Ό μμν©λλ€.- μ»΄ν¬λνΈλ νμ¬ μνμ λ°λΌ λ€λ₯Έ μ½ν μΈ λ₯Ό λ λλ§ν©λλ€.
useActionState
μ¬μ©νκΈ° (κ°μ - React 19 κΈ°λ₯)
useActionState
λ μμ§ μ μμΌλ‘ μ¬μ©ν μ μμ§λ§, μ¬μ© κ°λ₯ν΄μ‘μ λ ꡬνμ΄ μ΄λ»κ² 보μΌμ§, λ κΉλν μ κ·Ό λ°©μμ μ 곡νλμ§ λ³΄μ¬λλ¦¬κ² μ΅λλ€:
import React from 'react';
//import { useActionState } from 'react'; // μ¬μ© κ°λ₯ν΄μ§λ©΄ μ£Όμ ν΄μ
const productDetailsMachine = {
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loading',
},
},
loading: {
on: {
SUCCESS: 'success',
ERROR: 'error',
},
},
success: {
type: 'final',
},
error: {
on: {
FETCH: 'loading',
},
},
},
};
function ProductDetails({ productId }) {
const initialState = { state: productDetailsMachine.initial, data: null, error: null };
// κ°μ useActionState ꡬν
const [newState, dispatch] = React.useReducer(
(state, event) => {
const nextState = productDetailsMachine.states[state.state].on[event];
return nextState ? { ...state, state: nextState } : state; // μ νμ΄ μ μλμ§ μμ κ²½μ° λ€μ μν λλ νμ¬ μν λ°ν
},
initialState
);
const handleFetchProduct = async () => {
dispatch('FETCH');
try {
const response = await fetch(`https://api.example.com/products/${productId}`); // μ¬λ¬λΆμ API μλν¬μΈνΈλ‘ κ΅μ²΄νμΈμ
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// μ±κ³΅μ μΌλ‘ κ°μ Έμ΄ - λ°μ΄ν°μ ν¨κ» SUCCESS λμ€ν¨μΉ!
dispatch('SUCCESS');
// κ°μ Έμ¨ λ°μ΄ν°λ₯Ό λ‘컬 μνμ μ μ₯. 리λμ λ΄μμ λμ€ν¨μΉ μ¬μ© λΆκ°.
newState.data = data; // λμ€ν¨μ² μΈλΆμμ μ
λ°μ΄νΈ
} catch (error) {
// μ€λ₯ λ°μ - μ€λ₯ λ©μμ§μ ν¨κ» ERROR λμ€ν¨μΉ!
dispatch('ERROR');
// render()μμ νμλ μ λ³μμ μ€λ₯ μ μ₯
newState.error = error.message;
}
//}, initialState);
};
return (
μ ν μμΈ μ 보
{newState.state === 'idle' && }
{newState.state === 'loading' && λ‘λ© μ€...
}
{newState.state === 'success' && newState.data && (
{newState.data.name}
{newState.data.description}
κ°κ²©: ${newState.data.price}
)}
{newState.state === 'error' && newState.error && μ€λ₯: {newState.error}
}
);
}
export default ProductDetails;
μ€μ μ°Έκ³ : μ΄ μμ λ useActionState
κ° μμ§ μ μμΌλ‘ μ 곡λμ§ μκ³ μ νν APIκ° λ³κ²½λ μ μκΈ° λλ¬Έμ κ°μμ
λλ€. ν΅μ¬ λ‘μ§ μ€νμ μν΄ νμ€ useReducerλ‘ λ체νμ΅λλ€. νμ§λ§, μ΄ μμ μ μλλ useActionState
κ° μ¬μ© κ°λ₯ν΄μ‘μ λ *μ΄λ»κ²* μ¬μ©ν κ²μΈμ§λ₯Ό 보μ¬μ£Όλ κ²μ΄λ©°, useReducerλ₯Ό useActionStateλ‘ κ΅μ²΄ν΄μΌ ν©λλ€. λ―Έλμ useActionState
λ₯Ό μ¬μ©νλ©΄ μ΄ μ½λλ μ€λͺ
λ λλ‘ μ΅μνμ λ³κ²½μΌλ‘ μλνμ¬ λΉλκΈ° λ°μ΄ν° μ²λ¦¬λ₯Ό ν¬κ² λ¨μνν κ²μ
λλ€.
useActionState
λ₯Ό μν λ¨Έμ κ³Ό ν¨κ» μ¬μ©ν λμ μ΄μ
- κ΄μ¬μ¬μ λͺ νν λΆλ¦¬: μν λ‘μ§μ μν λ¨Έμ λ΄μ μΊ‘μνλκ³ , UI λ λλ§μ React μ»΄ν¬λνΈμμ μ²λ¦¬λ©λλ€.
- μ½λ κ°λ μ± ν₯μ: μν λ¨Έμ μ μ ν리μΌμ΄μ μ λμμ μκ°μ μΌλ‘ νννμ¬ μ΄ν΄νκ³ μ μ§λ³΄μνκΈ° λ μ½κ² λ§λλλ€.
- λ¨μνλ λΉλκΈ° μ²λ¦¬:
useActionState
λ λΉλκΈ° μ‘μ μ²λ¦¬λ₯Ό κ°μννμ¬ λ³΄μΌλ¬νλ μ΄νΈ μ½λλ₯Ό μ€μ λλ€. - ν₯μλ ν μ€νΈ μ©μ΄μ±: μν λ¨Έμ μ λ³Έμ§μ μΌλ‘ ν μ€νΈνκΈ° μ¬μ μ ν리μΌμ΄μ λμμ μ νμ±μ μ½κ² κ²μ¦ν μ μμ΅λλ€.
κ³ κΈ κ°λ λ° κ³ λ €μ¬ν
XState ν΅ν©
λ 볡μ‘ν μν κ΄λ¦¬ μꡬμ¬νμ΄ μλ κ²½μ°, XStateμ κ°μ μ μ© μν λ¨Έμ λΌμ΄λΈλ¬λ¦¬ μ¬μ©μ κ³ λ €ν΄ λ³΄μΈμ. XStateλ κ³μΈ΅μ μν, λ³λ ¬ μν, κ°λ, μ‘μ κ³Ό κ°μ κΈ°λ₯μ ν΅ν΄ μν λ¨Έμ μ μ μνκ³ κ΄λ¦¬νκΈ° μν κ°λ ₯νκ³ μ μ°ν νλ μμν¬λ₯Ό μ 곡ν©λλ€.
// XState μ¬μ© μμ
import { createMachine, useMachine } from 'xstate';
const productDetailsMachine = createMachine({
id: 'productDetails',
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loading',
},
},
loading: {
invoke: {
id: 'fetchProduct',
src: (context, event) => fetch(`https://api.example.com/products/${context.productId}`).then(res => res.json()),
onDone: {
target: 'success',
actions: assign({ product: (context, event) => event.data })
},
onError: {
target: 'error',
actions: assign({ error: (context, event) => event.data })
}
}
},
success: {
type: 'final',
},
error: {
on: {
FETCH: 'loading',
},
},
},
}, {
services: {
fetchProduct: (context, event) => fetch(`https://api.example.com/products/${context.productId}`).then(res => res.json())
}
});
μ΄λ μνλ₯Ό κ΄λ¦¬νλ λ μ μΈμ μ΄κ³ κ²¬κ³ ν λ°©λ²μ μ 곡ν©λλ€. npm install xstate
λ₯Ό μ¬μ©νμ¬ μ€μΉν΄μΌ ν©λλ€.
μ μ μν κ΄λ¦¬
μ¬λ¬ μ»΄ν¬λνΈμ κ±Έμ³ λ³΅μ‘ν μν κ΄λ¦¬ μꡬμ¬νμ΄ μλ μ ν리μΌμ΄μ μ κ²½μ°, Reduxλ Zustandμ κ°μ μ μ μν κ΄λ¦¬ μ루μ μ μν λ¨Έμ κ³Ό ν¨κ» μ¬μ©νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ. μ΄λ₯Ό ν΅ν΄ μ ν리μΌμ΄μ μ μνλ₯Ό μ€μ μ§μ€ννκ³ μ»΄ν¬λνΈ κ°μ μ½κ² 곡μ ν μ μμ΅λλ€.
μν λ¨Έμ ν μ€νΈνκΈ°
μν λ¨Έμ μ ν μ€νΈνλ κ²μ μ ν리μΌμ΄μ μ μ νμ±κ³Ό μ λ’°μ±μ 보μ₯νλ λ° λ§€μ° μ€μν©λλ€. Jestλ Mochaμ κ°μ ν μ€νΈ νλ μμν¬λ₯Ό μ¬μ©νμ¬ μν λ¨Έμ μ λν λ¨μ ν μ€νΈλ₯Ό μμ±νκ³ , μν κ° μ νμ΄ μμλλ‘ μ΄λ£¨μ΄μ§λμ§μ λ€μν μ΄λ²€νΈλ₯Ό μ¬λ°λ₯΄κ² μ²λ¦¬νλμ§ κ²μ¦ν μ μμ΅λλ€.
κ°λ¨ν μμ λ λ€μκ³Ό κ°μ΅λλ€:
// Jest ν
μ€νΈ μμ
import { interpret } from 'xstate';
import { productDetailsMachine } from './productDetailsMachine';
describe('productDetailsMachine', () => {
it('should transition from idle to loading on FETCH event', (done) => {
const service = interpret(productDetailsMachine).onTransition((state) => {
if (state.value === 'loading') {
expect(state.value).toBe('loading');
done();
}
});
service.start();
service.send('FETCH');
});
});
κ΅μ ν (i18n)
μ μΈκ³ μ¬μ©μλ₯Ό λμμΌλ‘ μ ν리μΌμ΄μ μ ꡬμΆν λ κ΅μ ν(i18n)λ νμμ μ λλ€. μν λ¨Έμ λ‘μ§κ³Ό UI λ λλ§μ΄ μ¬λ¬ μΈμ΄μ λ¬Ένμ λ§₯λ½μ μ§μνλλ‘ μ μ ν κ΅μ νλμλμ§ νμΈν΄μΌ ν©λλ€. λ€μμ κ³ λ €νμΈμ:
- ν μ€νΈ μ½ν μΈ : i18n λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ¬μ©μμ λ‘μΌμΌμ λ°λΌ ν μ€νΈ μ½ν μΈ λ₯Ό λ²μν©λλ€.
- λ μ§ λ° μκ° νμ: λ‘μΌμΌμ μΈμνλ λ μ§ λ° μκ° νμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ¬μ©μ μ§μμ λ§λ μ¬λ°λ₯Έ νμμΌλ‘ λ μ§μ μκ°μ νμν©λλ€.
- ν΅ν νμ: λ‘μΌμΌμ μΈμνλ ν΅ν νμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ¬μ©μ μ§μμ λ§λ μ¬λ°λ₯Έ νμμΌλ‘ ν΅ν κ°μ νμν©λλ€.
- μ«μ νμ: λ‘μΌμΌμ μΈμνλ μ«μ νμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ¬μ©μ μ§μμ λ§λ μ¬λ°λ₯Έ νμ(μ: μμμ κ΅¬λΆ κΈ°νΈ, μ² λ¨μ κ΅¬λΆ κΈ°νΈ)μΌλ‘ μ«μλ₯Ό νμν©λλ€.
- μ€λ₯Έμͺ½μμ μΌμͺ½(RTL) λ μ΄μμ: μλμ΄ λ° νλΈλ¦¬μ΄μ κ°μ μΈμ΄λ₯Ό μν΄ RTL λ μ΄μμμ μ§μν©λλ€.
μ΄λ¬ν i18n μΈ‘λ©΄μ κ³ λ €ν¨μΌλ‘μ¨ μ μΈκ³ μ¬μ©μμκ² μ κ·Ό κ°λ₯νκ³ μ¬μ©μ μΉνμ μΈ μ ν리μΌμ΄μ μ 보μ₯ν μ μμ΅λλ€.
κ²°λ‘
Reactμ useActionState
λ₯Ό μν λ¨Έμ κ³Ό κ²°ν©νλ κ²μ κ²¬κ³ νκ³ μμΈ‘ κ°λ₯ν μ¬μ©μ μΈν°νμ΄μ€λ₯Ό ꡬμΆνκΈ° μν κ°λ ₯ν μ κ·Ό λ°©μμ μ 곡ν©λλ€. μν λ‘μ§μ UI λ λλ§κ³Ό λΆλ¦¬νκ³ λͺ
νν μ μ΄ νλ¦μ κ°μ ν¨μΌλ‘μ¨ μν λ¨Έμ μ μ½λ ꡬμ±, μ μ§λ³΄μμ± λ° ν
μ€νΈ μ©μ΄μ±μ ν₯μμν΅λλ€. useActionState
λ μμ§ μΆμ μμ κΈ°λ₯μ΄μ§λ§, μ§κΈ μν λ¨Έμ μ ν΅ν©νλ λ°©λ²μ μ΄ν΄νλ©΄ μ΄ κΈ°λ₯μ΄ μΆμλμμ λ κ·Έ μ΄μ μ νμ©ν μ€λΉκ° λ κ²μ
λλ€. XStateμ κ°μ λΌμ΄λΈλ¬λ¦¬λ ν¨μ¬ λ κ³ κΈ μν κ΄λ¦¬ κΈ°λ₯μ μ 곡νμ¬ λ³΅μ‘ν μ ν리μΌμ΄μ
λ‘μ§μ λ μ½κ² μ²λ¦¬ν μ μλλ‘ ν©λλ€.
μν λ¨Έμ κ³Ό useActionState
λ₯Ό μ±νν¨μΌλ‘μ¨ React κ°λ° κΈ°μ μ ν λ¨κ³ λμ΄μ¬λ¦¬κ³ μ μΈκ³ μ¬μ©μμκ² λ μ λ’°ν μ μκ³ μ μ§λ³΄μνκΈ° μ¬μ°λ©° μ¬μ©μ μΉνμ μΈ μ ν리μΌμ΄μ
μ ꡬμΆν μ μμ΅λλ€.