이 글은 HTTP 요청 내용에서 이어집니다.
HTTP 요청 보내기
HTTP 요청의 기본 개념 클라이언트에 직접적으로 서버를 연결하면 자바스크립트 코드는 누구나 확인할 수 있기 때문에 인증 정보를 노출시키는 행위이며 보안에 취약해집니다. HTTP 요청에 대한 A
iltae.tistory.com
투 두 리스트를 예시로 HTTP 요청을 위한 커스텀 훅 구성을 먼저 해봅시다.
use-http.js
import { useState, useCallback } from "react";
const useHttp = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
// requestConfig를 매개변수로 하고 이는 URL을 포함해 여러 설정 사항들을 포함하는 객체여야함
// 그 객체에 이용할 값들을 연결해 줌
const sendRequest = useCallback(async (requestConfig, applyData) => {
setIsLoading(true);
setError(null);
try {
const response = await fetch(
requestConfig.url, {
method: requestConfig.method ? requestConfig.method : 'GET',
headers: requestConfig.headers ? requestConfig : {},
body: requestConfig.body ? JSON.stringify(requestConfig.body) : null
}
);
if (!response.ok) {
throw new Error('Request failed!');
}
const data = await response.json();
// 함수를 매개변수로 받아 데이터를 넘겨줌
applyData(data);
} catch (err) {
setError(err.message || 'Something went wrong!');
}
setIsLoading(false);
}, []);
// 로딩 상태, 에러상태 그리고 함수를 반환함
return {
// isLoading: isLoading,
// error: error,
// sendRequest: sendRequest
// 모던 자바스크립트에서 속성명과 변수명이 같은 경우 이렇게 편하게 줄일 수 있음
isLoading,
error,
sendRequest
}
};
export default useHttp;
- 의존성을 최소화하기 위해 useHttp에 인자를 설정하지 않고 sendRequest에 설정해 줍니다.
- 요청의 여러 경우를 유동적으로 대처하기 위해 값이 빌 경우에 대한 설정을 해줍니다.
- 여러 상태와 요청 함수를 반환해 줍니다.
- 이 함수를 호출할 때 의존성 배열에 함수를 넣어야 해 무한 루프를 방지하기 위해 useCallback으로 함수를 저장합니다.
그다음에 이를 불러올 컴퍼넌트를 구성해 보겠습니다.
App.js
import React, { useEffect, useState, useCallback } from 'react';
import useHttp from './hooks/use-http';
function App() {
const [tasks, setTasks] = useState([]);
// 커스텀 훅에 인자를 연결하고
// 응답을 가져오는 시점에 구조를 분해해서 받아옴
// sendRequest 함수의 fetchTasks 별칭을 달아줌
const { isLoading, error, sendRequest: fetchTasks } = useHttp();
useEffect(() => {
// firebase에서 받아온 데이터를 가공하는 함수임
// 랜덤으로 키값을 생성하기 때문에 가공이 이렇게 까다로워짐
// 응답 오는 데이터에 알맞게 각자 가공해주면 됨
const transformTasks = (tasksObj) => {
const loadedTasks = [];
for (const taskKey in taskObj) {
loadedTasks.push({ id: taskKey, text: taskObj[taskKey].texy });
}
setTasks(loadedTasks);
};
fetchTasks({ url: 'http://어쩌구저쩌구' }, transformTasks);
}, [fetchTasks]);
return (
<React.Fragment>
<!--Tasks 컴퍼넌트에 커스텀 훅을 통해 받은 내용들은 내려줌-->
<Tasks
items={tasks}
loading={isLoading}
error={error}
onFetch={fetchTasks}
/>
</React.Fragment>
);
}
export default App;
- 커스텀 훅을 연결하고 받아오는 데이터를 가공하여 Tasks 컴퍼넌트에 내려줍니다.
- 기본적으로 GET이기 때문에 requestConfig가 심플하게 끝납니다.
다음으로 POST 요청도 구성해 보겠습니다.
NewTask.js
import { useState } from "react";
import useHttp from "./hooks/use-http";
const NewTask = (props) => {
const { isLoading, error, sendRequest: sendTaskRequest } = useHttp();
const createTask = (taskText, taskData) => {
const generatedId = taskData.name;
const createdTask = { id: generatedId, text: taskText };
// 설명은 빠졌지만 APP에서 간단히 기존의 task에 합치는 함수
props.onAddTask(createTask);
}
const enterTaskHandler = async (taskText) => {
sendTaskRequest(
{
url: 'http://어쩌구저쩌구',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: { text: taskText }
},
// createTask를 바인딩 하여 createTask 함수에서 taskText를 쓸 수 있게 함
createTask.bind(null, taskText));
}
}
...
- POST 요청은 일반적으로 화면을 리렌더링 하는 게 없기에 useEffect를 사용할 필요가 없습니다.
- bind 메서드를 이용하여 enterTaskHandler 함수를 호출 즉시가 아닌 사전에 구성할 수 있게 합니다.
'REACT' 카테고리의 다른 글
| useContext 훅 (5) | 2023.03.03 |
|---|---|
| useReducer 훅 (5) | 2023.03.02 |
| 커스텀 훅(Custom Hook) (10) | 2023.02.16 |
| 리액트 최적화 테크닉 (7) | 2023.02.14 |
| HTTP 요청 보내기 (8) | 2023.02.13 |