[React] FITPET : 숙소 상세보기 API 연동하기

숙소 상세보기 페이지는 숙소 리스트 페이지에서 상세보기 버튼을 클릭하면 이동하게 되는 페이지 입니다. 상세보기 버튼에 불러올 숙소의 id값을 넣어줘 id값과 일치한 데이터들을 불러오도록 구현하였습니다.

1. HotelService.js에 getHotelAbout() 추가하기.

services 폴더에 HotelService.js 파일을 만들고 여기에 숙소 페이지 내에서 불러오는 모든 API 를 관리합니다.
상세보기 페이지를 관리할 getHotelAbout()을 추가해줍니다.

HotelService.js

import axios from 'axios';

export default class HotelService {
// 호텔 리스트
  static async getHotelList(page) {
    const response = await axios.get(`/api/lodging/list/?nowPage=${page}`);
    return response;
  }

  // 호텔 상세보기 (객실 정보)
  static async getHotelAbout(hotelId) {
    const response = await axios.get(`/api/lodging/${hotelId}`);
    return response;
  }
}

2. hotelAbout.js에서 reducer, action, saga 관리하기

redux > modules 폴더 안에 hotelAbout.js 파일을 생성하여 reducer, action, saga를 관리합니다.

hotelAbout.js

import { call, put, takeEvery } from '@redux-saga/core/effects';
import HotelService from '../../services/HotelService';
import { hotelListFail, hotelListSaga, hotelListStart } from './hotelList';

// namespace
const namespace = 'fitpet/hotelAbout';

// action types
const START = namespace + '/START';
const SUCCESS = namespace + '/SUCCESS';
const FAIL = namespace + '/FAIL';

// initiall state
const initalState = { hotelAbout: [], error: null };

// reducer
export default function hotelAbout(state = initalState, action) {
  switch (action.type) {
    case START:
      return { hotelAbout: [], errer: null };

    case SUCCESS:
      return { ...state, hotelAbout: action.hotelAbout };

    case FAIL:
      return { ...state, error: action.error };

    default:
      return state;
  }
}

// action creators
export const hotelAboutStart = () => ({ type: START });
export const hotelAboutSuccess = (hotelAbout) => ({
  type: SUCCESS,
  hotelAbout,
});

export const hotelAboutFail = (error) => ({ type: FAIL, error });

// saga
const HOTEL_ABOUT_SAGA = namespace + '/HOTEL_ABOUT_SAGA';

export function* hotelAboutSaga(action) {
  try {
    yield put(hotelListStart());
    const response = yield call(HotelService.getHotelAbout);
    yield put(hotelAboutSuccess(response.data));
  } catch (error) {
    yield put(hotelListFail(error));
  }
}

// watch saga
export function* watchHotelList() {
  yield takeEvery(HOTEL_ABOUT_SAGA, hotelListSaga);
}

HotelAboutContainer.jsx에 추가해줍니다.

import React, { useCallback } from 'react';
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import HotelAbout from '../components/hotel/hotel_about/HotelAbout';
import { closeRoomDetail, openRoomDetail } from '../redux/modules/modal';

const HotelAboutContainer = () => {
  const dispatch = useDispatch();
  const roomDetailOpen = useSelector((state) => state.modal.roomDetailOpen);
  **const hotelaboutInfo = useSelector(
    (state) => state.hotelAbout.hotelaboutInfo,
  );**

  // 객실 상세 창 열기
  const showRoomDetail = useCallback(() => {
    dispatch(openRoomDetail());
  }, [dispatch, roomDetailOpen]);

  // 객실 상세 창 닫기
  const hideRoomDetail = useCallback(() => {
    dispatch(closeRoomDetail());
  }, [dispatch]);

  useEffect(() => {
    if (roomDetailOpen) {
      document.body.style.cssText = `
      position:fixed;
      top: -${window.scrollY}px;
      overflow-y: scroll;
      width: 100%;
    `;
    }

    return () => {
      const scrollY = document.body.style.top;
      document.body.style.cssText = '';
      window.scrollTo(window.scrollY, parseInt(scrollY || '0', 10) * -1);
    };
  }, [roomDetailOpen]);

  return (
    <HotelAbout
      **hotelaboutInfo={hotelaboutInfo}**
      showRoomDetail={showRoomDetail}
      roomDetailOpen={roomDetailOpen}
      hideRoomDetail={hideRoomDetail}
    />
  );
};

export default HotelAboutContainer;

좋은 웹페이지 즐겨찾기