일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- exception
- 객체 비교
- 컬렉션프레임워크
- 자동차수리시스템
- NestedFor
- abstract
- 오라클
- oracle
- 예외미루기
- 자바
- Java
- 생성자오버로드
- 대덕인재개발원
- 어윈 사용법
- 한국건설관리시스템
- GRANT VIEW
- 인터페이스
- 추상메서드
- 메소드오버로딩
- EnhancedFor
- 컬렉션 타입
- 예외처리
- 다형성
- cursor문
- 집합_SET
- 사용자예외클래스생성
- 환경설정
- 참조형변수
- 정수형타입
- 제네릭
- Today
- Total
거니의 velog
(12) 리액트와 API 서버 통신 2 본문
4. 네비게이션 관련 커스텀 훅
* ReadComponent가 완성되기 위해서 남은 작업은 다시 목록 화면으로 이동하는 기능이 추가되어야 한다. 리액트에서 화면의 구성은 컴포넌트를 이용해서 처리할 수 있지만, 컴포넌트들 내부에서 만들어지는 공통적인 코드의 경우 커스텀 훅(custom hook)을 이용해서 작성한다.
* 예제의 경우 조회 화면에서는 다시 목록 화면으로 이동해야 하는 기능이 필요하고 이를 구현하기 위해서 useNavigate()나 useSearchParams를 이용해야만 한다. 이렇게 만들어진 기능은 등록이나 수정/삭제 화면에서도 동일하게 사용된다.
(1) 목록 페이지로 이동
* 커스텀 훅을 제작하기 위해서 프로젝트의 src 폴더에 hooks 폴더를 추가하고 useCustomMove.js 파일을 추가한다(커스텀 훅은 반드시 'use-' 접두사로 시작해야 한다).
import {
createSearchParams,
useNavigate,
useSearchParams,
} from "react-router-dom";
const getNum = (param, defaultValue) => {
if (!param) {
return defaultValue;
}
return parseInt(param);
};
const useCustomMove = () => {
const navigate = useNavigate();
const [queryParams] = useSearchParams();
const page = getNum(queryParams.get("page"), 1);
const size = getNum(queryParams.get("size"), 10);
const queryDefault = createSearchParams({ page, size }).toString(); // 새로 추가
const moveToList = (pageParam) => {
let queryStr = "";
if (pageParam) {
const pageNum = getNum(pageParam.page, 1);
const sizeNum = getNum(pageParam.size, 10);
queryStr = createSearchParams({
page: pageNum,
size: sizeNum,
}).toString();
} else {
queryStr = queryDefault;
}
navigate({ pathname: `../list`, search: queryStr });
};
return { moveToList, page, size };
};
export default useCustomMove;
* useCustomMove()의 내부에는 useNavigate() 와 useSearchParams() 를 이용해서 원하는 기능을 moveToList() 로 만들고 이를 page, size 와 함께 반환한다. 외부에서 useCustomMove()를 이용하면 이전에 비해서 간단히 useNavigate() 를 이용하게 되고 반환된 데이터들 중에서 필요한 데이터만 선별해서 사용할 수 있다.
* ReadComponent에서 useCustomMove()의 실행 결과 중에서 moveToList()를 이용하고 버튼을 추가해 보자.
import React, { useEffect, useState } from "react";
import { getOne } from "../../api/todoApi";
import useCustomMove from "../../hooks/useCustomMove";
(...)
const ReadComponent = ({ tno }) => {
const [todo, setTodo] = useState(initState);
const { moveToList } = useCustomMove();
useEffect(() => {
getOne(tno).then((data) => {
console.log(data);
setTodo(data);
});
}, [tno]);
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
{makeDiv("Tno", todo.tno)}
{makeDiv("Writer", todo.writer)}
{makeDiv("Title", todo.title)}
{makeDiv("Due Date", todo.dueDate)}
{makeDiv("Complete", todo.complete ? "Completed" : "Not Yet")}
{/* buttons starts... */}
<div className="flex justify-end p-4">
<button
type="button"
className="rounded p-4 m-2 text-xl w-32 text-white bg-blue-500"
onClick={() => moveToList()}
>
List
</button>
</div>
</div>
);
};
export default ReadComponent;
* 화면에서 ReadComponent는 하단 오른쪽에 'List' 버튼이 생성되고 클릭 시에 '/todo/list' 로 이동하게 된다. '/todo/list'로 이동할 때 'page=1&size=10'이 자동으로 처리된다.
(2) 수정/삭제 페이지로 이동
* 커스텀 훅을 이용하면 여러 컴포넌트들이 필요한 기능을 하나의 함수로 묶어서 처리할 수 있다는 장점이 있다. useCustomMove의 기능을 조금 더 확장해서 수정/삭제로 이동할 수 있는 기능을 추가해 본다.
import {
createSearchParams,
useNavigate,
useSearchParams,
} from "react-router-dom";
const getNum = (param, defaultValue) => {
(...)
};
const useCustomMove = () => {
(...)
const moveToList = (pageParam) => {
(...)
};
const moveToModify = (num) => {
console.log(queryDefault);
navigate({
pathname: `../modify/${num}`,
search: queryDefault, //수정시에 기존의 쿼리 스트링 유지를 위해
});
};
return { moveToList, moveToModify, page, size }; // moveToModify 추가
};
export default useCustomMove;
* useCustomMove 에는 moveToModify() 를 구현하고 외부에서 사용 가능하도록 return 구문에 추가해 준다. 이를 ReadComponent 에서는 수정/삭제로 이동할 수 있는 버튼을 추가해서 사용한다.
import React, { useEffect, useState } from "react";
import { getOne } from "../../api/todoApi";
import useCustomMove from "../../hooks/useCustomMove";
(...)
const ReadComponent = ({ tno }) => {
const [todo, setTodo] = useState(initState);
// 이동과 관련된 기능은 모두 useCustomMove() 로
const { moveToList, moveToModify } = useCustomMove();
useEffect(() => {
getOne(tno).then((data) => {
console.log(data);
setTodo(data);
});
}, [tno]);
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
{makeDiv("Tno", todo.tno)}
{makeDiv("Writer", todo.writer)}
{makeDiv("Title", todo.title)}
{makeDiv("Due Date", todo.dueDate)}
{makeDiv("Complete", todo.complete ? "Completed" : "Not Yet")}
{/* buttons starts... */}
<div className="flex justify-end p-4">
<button
type="button"
className="rounded p-4 m-2 text-xl w-32 text-white bg-blue-500"
onClick={() => moveToList()}
>
List
</button>
<button
type="button"
className="rounded p-4 m-2 text-xl w-32 text-white bg-red-500"
onClick={() => moveToModify(tno)}
>
Modify
</button>
</div>
</div>
);
};
export default ReadComponent;
* 변경된 ReadComponent는 useCustomMove()의 결과인 movoToModify()를 이용할 수 있으므로, 적은 양의 코드만으로도 원하는 기능들을 처리할 수 있게 되었다. 브라우저의 조회 화면에서 'Modify' 버튼을 클릭해서 이동하는 것을 확인해 보자.
* 이전 장의 경우 조회 페이지로 이동하는 기능은 pages/todo/ReadPage에서 처리되었지만, ReadComponent가 필요한 기능을 useCustomMove를 이용해서 처리할 수 있으므로 기존의 useNavigate 를 이용하는 코드를 삭제할 수 있다.
import React from "react";
import { useParams } from "react-router-dom";
import ReadComponent from "../../components/todo/ReadComponent";
const ReadPage = () => {
const { tno } = useParams();
return (
/* text-3xl 삭제 */
<div className="font-extrabold w-full bg-white mt-6">
<div className="text-2xl">Todo Read Page Component {tno}</div>
<ReadComponent tno={tno}></ReadComponent>
</div>
);
};
export default ReadPage;
* 코드가 훨씬 더 간결해 진 모습이다.
'SpringBoot_React 풀스택 프로젝트' 카테고리의 다른 글
(14) 리액트와 API 서버 통신 4 (0) | 2024.02.28 |
---|---|
(13) 리액트와 API 서버 통신 3 (0) | 2024.02.28 |
(11) 리액트와 API 서버 통신 1 (0) | 2024.02.28 |
(10) 스프링 부트와 API 서버 5 (0) | 2024.02.28 |
(9) 스프링 부트와 API 서버 4 (0) | 2024.02.28 |