-
[Spring Boot/React] 카드 신청 페이지 제작Project/외국인 관광객을 위한 카드 플랫폼 2024. 8. 10. 23:03
- 카드 신청 폼 만들기
자료 참고
- 문제 : 카드 신청할 때 입력된 카드 정보 데이터들 card 테이블에 insert하고 싶은데 단계별로 넣을 때마다 실시간으로 정보 하나씩 insert해서 db에 들어갔다가 나오는 과정으로 설계하려했지만 더 효율적인 방법이 있을 거 같아 고민
- 해결: 리액트의 useContext사용해 프론트 단에서 데이터 모아서 마지막에 한꺼번에 입력시키고 백으로 insert하기로 함
https://ko.react.dev/reference/react/useContext
useContext는 React의 훅(hook) 중 하나로, 컨텍스트(Context) 객체의 현재 값을 가져오기 위해 사용됩니다. 컨텍스트는 컴포넌트 트리 전체에 걸쳐 데이터를 전역적으로 전달할 수 있는 방법을 제공합니다. 이는 props를 통해 데이터를 전달해야 하는 필요성을 줄여줍니다
1. Context 생성 및 제공
import React, { createContext, useContext, useState } from 'react'; const CardContext = createContext(); // 컨텍스트 객체를 생성 // useContext를 사용하여 CardContext의 현재 값을 반환 export const useCardContext = () => { return useContext(CardContext); }; export const CardProvider = ({children}) => { const [produceCardOffer, setProduceCardOffer] = useState({ "card_id":"", "card_account":"", "card_balance" : "", "card_number":"", "card_password":"", "card_pickup":"", "card_status":"", "cvv_code":"", "expiration_date":"", "issue_date":"", "payment_bank":"", "payment_date":"", "pickup_date":"", "transportation":"", "card_type_id":"", "member_id":"" }); return ( <CardContext.Provider value={{produceCardOffer, setProduceCardOffer}}> {children} </CardContext.Provider> ) }
- CardContext를 생성합니다.
- useCardContext는 useContext를 사용하여 CardContext의 현재 값을 반환하는 커스텀 훅입니다.
- CardProvider 컴포넌트는 produceCardOffer 상태와 그 상태를 업데이트하는 setProduceCardOffer 함수를 CardContext.Provider를 통해 하위 컴포넌트에 제공합니다.
2. CardProvider로 Context 감싸기
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { CardProvider } from './CardContext'; ReactDOM.render( <CardProvider> <App /> </CardProvider>, document.getElementById('root') );
CardProvider로 App을 감싸서 CardContext를 앱 전체에 제공할 수 있도록 합니다.
3. Context 사용하기 (예시: Card1 컴포넌트)
import React, { useState, useEffect } from 'react'; import '../../assets/Card.css'; import Flickity from 'react-flickity-component'; import axios from 'axios'; import { useCardContext } from './CardContext'; import { useNavigate } from 'react-router-dom'; function Card1() { const [selectedCard, setSelectedCard] = useState(null); const [cards, setCards] = useState([]); const [isLoading, setIsLoading] = useState(true); const {produceCardOffer, setProduceCardOffer} = useCardContext(); let navigate = useNavigate(); const flickityOptions = { cellAlign: 'right', pageDots: false, groupCells: '20%', selectedAttraction: 0.03, friction: 0.15, }; useEffect(() => { axios.get('/api/cards') .then(response => { console.log('Fetched cards:', response.data); setCards(response.data); if (response.data.length > 0) { setSelectedCard(response.data[0]); } setIsLoading(false); // 데이터 로드 완료 }) .catch(error => { console.error('There was an error fetching the cards!', error); setIsLoading(false); // 데이터 로드 실패 }); }, []); const handleChange = (index) => { if (cards.length > 0 && index < cards.length) { setSelectedCard(cards[index]); // console.log('Selected card:', cards[index]); } else { console.log("카드 데이터가 아직 로드되지 않았습니다."); } }; return ( <div className='container'> <div className='header'> <div>카드 신청</div> </div> <div className='content'> <div className='carousel-container'> {isLoading ? ( <div>카드 불러오는 중...</div> ) : ( <Flickity className='carousel' options={flickityOptions} flickityRef={(c) => { if (c) { c.on('change', (index) => handleChange(index)); } }} > {cards.map((card, index) => ( <div className="carousel-cell" key={card.cardTypeId}> <img src={card.cardImg} className="p" alt={card.cardName} /> <div className='card-info'> <div>카드이름: {card.cardName}</div> <div>카드사용목적: {card.cardUsage}</div> <div>카드한도: {card.cardLimit}</div> <div>연회비: {card.annualFee}</div> </div> </div> ))} </Flickity> )} </div> {selectedCard && ( <div className='selected-card'> <div>선택한 카드이름: {selectedCard.cardName}</div> <div>카드사용목적: {selectedCard.cardUsage}</div> <div>카드한도: {selectedCard.cardLimit}</div> <div>연회비: {selectedCard.annualFee}</div> </div> )} </div> <button onClick={() => { if(selectedCard) { setProduceCardOffer(prevState => ({ ...prevState, card_type_id:selectedCard.cardTypeId // 선택된 카드 타입 })); setTimeout(() => navigate('/card2'), 300); }else{ console.log('카드가 선택되지 않았습니다.'); } }}>신청하기</button> <div className='menubar'></div> </div> ); } export default Card1;
- Card1 컴포넌트에서 useCardContext를 사용하여 produceCardOffer와 setProduceCardOffer를 가져옵니다.
- 사용자가 카드 신청 버튼을 클릭하면 selectedCard의 cardTypeId를 produceCardOffer 상태에 업데이트하고, 다음 페이지로 이동합니다.
이와 같은 방식으로 다른 컴포넌트 (Card2, Card3, CardForm, Card5)에서도 useCardContext를 사용하여 produceCardOffer 상태를 가져오고 업데이트합니다. 각 컴포넌트는 필요에 따라 produceCardOffer의 특정 필드를 업데이트하고, 폼 제출 시 해당 데이터를 다음 단계로 전달합니다.
4. 제출
import React from 'react'; import { useCardContext } from './CardContext'; function Card6(props) { const { produceCardOffer } = useCardContext(); return ( <div> <h3>카드 발급이 완료되었습니다.</h3> <pre>{JSON.stringify(produceCardOffer, null, 2)}</pre> {/* 데이터 확인 */} </div> ); } export default Card6;
- <pre> 태그 내에 produceCardOffer 객체를 JSON 형식으로 변환하여 출력합니다. JSON.stringify(produceCardOffer, null, 2)는 produceCardOffer 객체를 JSON 문자열로 변환하며, 두 번째 인자는 들여쓰기(indentation)를 위해 사용됩니다.
- 이렇게 하면 produceCardOffer의 내용을 포맷팅된 JSON 형식으로 화면에 표시할 수 있습니다.
'Project > 외국인 관광객을 위한 카드 플랫폼' 카테고리의 다른 글
[Spring Boot/React] 다음 주소 api 연결하기 (0) 2024.08.24 [Spring Boot/React] 카드 번호, CVV 코드 랜덤 생성 및 카드 정보 DB에 insert (0) 2024.08.13 [Spring Boot/React] 소비 패턴 그래프 생성 시 백과 연동 문제 해결 (0) 2024.08.09 [Spring Boot/React] Google Charts API 연동 - 주간 소비 리포트 만들기 (0) 2024.08.09 [Spring Boot/React] 카드 사용 내역 페이지 만들기 (0) 2024.08.08