alova의 진정한 힘을 발휘할 수 있는 클라이언트 UI 프레임워크와 함께 사용하는 방법을 알아보겠습니다.
UI 프레임워크에서 사용하면 alova가 응답 요청 상태를 자동으로 관리할 수 있을 뿐만 아니라, 특정 규칙을 통해 요청이 전송되어야 하는 시기를 자동으로 제어할 수도 있습니다.
alova는 세 가지 핵심 useHook 구현 요청 타이밍을 제공합니다: useRequest, useWatcher, useFetcher.
요청이 언제 전송되어야 하는지를 제어하고, 동시에 loading/data/error 등 요청의 응답 상태를 생성하고 유지할 것이며, 이러한 반응 상태(reactive states)를 뷰에서 직접 사용할 수 있으며, 상태가 변경되면 그에 따라 뷰도 변경됩니다.
요청 전략을 사용하기 전에 alova 인스턴스에 해당 statesHook을 설정해야 합니다. 프로젝트에서 사용하는 UI 프레임워크와 일치해야 합니다. 이는 매우 중요합니다. UI 프레임워크에 대한 반응형 상태(responsive states)를 생성해야 함을 alova에게 알려주게 됩니다.
import { createAlova } from 'alova';
import VueHook from 'alova/vue';
export const alovaInstance = createAlova({
// ...
statesHook: VueHook
});
useRequest는 가장 일반적으로 사용되는 요청 전략입니다. 이는 loading/data/error 등과 같은 요청의 응답 상태(responsive states)를 생성하고 유지하는 데 도움이 될 수 있습니다. 이러한 응답 상태를 뷰에서 직접 사용할 수 있습니다. 변경되면 뷰도 그에 따라 변경됩니다.
useRequest는 요청 전송을 의미합니다. 호출되면 기본적으로 요청이 전송됩니다.
// alova 인스턴스를 사용하여 메소드를 생성하고, 이를 useRequest에 전달하여 요청을 보냅니다.
const { loading, data, error, send, update, onSuccess } = useRequest(
alovaInstance.Get('/todos/1', {
cacheFor: 0
}),
{
initialData: {}, // 초기 데이터 설정
immediate: true // 즉시 요청 여부(기본값 true)
}
);
onSuccess(event => {
event.method; // method
event.data; // response data
});
const handleSend = () => {
send();
};
const handleUpdate = () => {
update({
data: { title: 'new title' }
});
// update 함수 or 직접 수정
// data.value = { title: 'new title' };
};
<div v-if="loading">로딩중</div>
<div v-else-if="error">{{ error.message }}</div>
<div v-else>
<div>Request result: {{ data }}</div>
<button @click="handleSend">수동 요청 전송</button>
<button @click="handleUpdate">수동 데이터 수정</button>
</div>
⚠️ UseHook 사용 명세
useRequest는 컴포넌트 내부에서 요청을 보내는 데에만 사용할 수 있습니다.
컴포넌트 외부에서는 메소드 인스턴스를 통해 직접 요청을 보낼 수 있으며,useRequest사용은 훅 사용 규칙을 준수해야 합니다. 즉, 함수의 최상위 레벨에서만 호출할 수 있습니다.
❌❌❌루프, 조건문 또는 하위 함수에서 호출하는 것은 권장되지 않습니다.
아래 예제에서, 클릭 콜백 함수에서 사용 시 정상적으로 요청이 시작될 수는 있지만, UseHook에서 반환된 응답 데이터를 뷰에서 사용할 수 없으며, 루프 및 조건문에서도 마찬가지입니다.// ❌ bad const handleClick = () => { const { loading, data } = useRequest(getter); // 클릭 이벤트 핸들러 내부에서 호출 }; // 반환된 데이터(loading, data)가 뷰에서 제대로 사용되지 않습니다. // --- // ✅ good const { loading, data, send } = useRequest(getter, { // 컴포넌트의 최상위 레벨에서 호출 immediate: false // 초기에는 요청을 보내지 않는 옵션 }); const handleClick = () => { send(); // send 함수를 호출하여 요청 };
useRequest는 컴포넌트 함수의 최상위 레벨에서만 호출- 컴포넌트 외부에서는 (
useRequest를 사용할 수 없으므로) 메소드 인스턴스를 통해 직접 요청- 훅은 최상위 레벨에서 선언하고, 필요한 경우 콜백 함수에서 훅에서 제공하는 메소드를 호출하여 작업을 수행
새 할 일 항목을 생성해야 하는 경우, 먼저 기본 전송 요청을 해제하고 수동 트리거 요청으로 전환한 후 useRequest에서 send 함수를 받아 요청을 수동으로 보낼 수 있습니다.
send 함수는 응답 데이터가 포함된 Promise 인스턴스를 반환하며, 요청 응답 후 해결 상태(resolve state)로 변경됩니다.
이때 send 함수로 전달된 매개변수를 받기 위해서는, useRequest의 첫 번째 매개변수를 메소드 핸들러 함수로 설정하면 됩니다.
// send 함수의 매개변수가 여기에서 수신됩니다.
const { send: addTodo } = useRequest(newTodo => alovaInstance.Post('/todo', 👉newTodo), {
immediate: false // 기본 전송 해제
});
const handleAddTodo = () => {
const newTodo = {
title: 'new todo item',
time: new Date().toLocaleString()
};
// send 함수는 응답 데이터를 받을 수 있는 Promise 객체를 반환합니다. -> 요청 성공/실패 처리
addTodo(👉newTodo)
.then(result => {
console.log('추가 성공. 응답 데이터:', result);
})
.catch(error => {
console.log('추가 실패. 오류 메시지:', error);
});
};
send 함수를 통해 요청을 자유롭게 반복할 수 있습니다.
useRequest를 사용할 때, 요청이 성공하기 전에 해당 data 값은 기본적으로 undefined 이지만,
요청이 성공하기 전에 초기 값을 갖는 data가 필요한 경우도 있습니다.
예를 들어, 목록을 요청할 때 일반적으로 목록을 []로 초기화해야 합니다. 그렇지 않으면 목록을 렌더링할 때 오류가 발생합니다.
useRequest(todoListGetter, {
initialData: []
});