React+Redux

리액트 자식 컴포넌트 함수 호출하기

디비드킴 2023. 1. 18. 17:42

https://babycoder05.tistory.com/entry/%EB%B6%80%EB%AA%A8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90%EC%84%9C-%EC%9E%90%EC%8B%9D-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C%ED%95%98%EA%B8%B0

 

React 부모 컴포넌트에서 자식 컴포넌트 함수 호출하기 - useImperativeHandle

React 에서 props 의 개념에 대해 익숙해졌다면, 부모 컴포넌트의 state 와 함수를 가져다 쓰는 것이 어렵지 않을 것이다. 그러나 만약 자식 컴포넌트의 함수를 부모 컴포넌트에서 사용해야 한다면

babycoder05.tistory.com

예약페이지에서 결제창 호출 컴포넌트를 사용 하려 했다 

자식 함수를 호출해야하는데 vue에서 그렇듯 리액트에서도 ref로 하면될거 같은 생각으로 찾아보았다

결과는 위글처럼 사용할 수 있었다

 

부모 컴포넌트

import "../assets/css/common.css";

import { useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSearchParams, useParams } from 'react-router-dom';
import { getProductsAndSeatInfo, saveReservation } from '../api/reservation/ReservationApi';
import { ReserAction } from "../reducers/ReserReducers"
import PaymentCompo from "../component/payment/PaymentCompo";
import ProductCompo from "../component/reservation/ProductCompo";
import CproductCompo from "../component/reservation/CproductCompo";
import TimeTableCompo from "../component/reservation/TimeTableCompo";
/**
 * 예약 시도 페이지 
 * @returns page
 */
function ReservationProPage() {
  const params = useParams();
  const [searchParams, setSearchParams] = useSearchParams();
  const paymentRef = useRef();
  const dispatch = useDispatch();
  const state = useSelector((state) => state);
  /**
   * 해당 좌석의 메뉴 예약내역 api 요청함수
   * @param {int} kindId 
   */
  let request = async (kindId) => {
    try {
      let response = await getProductsAndSeatInfo(params.seatId, kindId);
      let data = response.data;
      console.log(response);
      dispatch(ReserAction.setProducts({ products: data.products }));
      dispatch(ReserAction.setTimes({ times: data.times }));
    } catch (error) {
      console.log(error);
      alert('해당좌석의 시간/메뉴 불러오는데 실패 했습니다');
    }
  }
  /**
   * 페이지/혹은 제품 변경시 감지
   */
  useEffect(() => {
    request(searchParams.get('k'))
  }, [searchParams.get('k')]);
  /**
   * 품목 카테고리 변경
   * @param {int} kindId 
   */
  function changeKind(kindId) {
    searchParams.set('k', kindId);
    searchParams.set('kp', 1);
    setSearchParams(searchParams);
  }
  /**
   * 예약 하기 버튼 클릭시
   */
  let order = async () => {
    try {
      let response = await saveReservation(JSON.stringify({ "choiceProducts": state.ReserReducers.choiceProducts, "choiceTimes": state.ReserReducers.choiceTimes }));
      console.log(response);
      let data = response.data;
      paymentRef.current.on_pay(data);
    } catch (error) {
      console.log(error);
      alert('예약에 실패했습니다');
    }
  }
  return (
    <div>
      <hr></hr>
      <h2>상품</h2>
      <hr></hr>
      <div>
        <button onClick={() => { changeKind(1) }}>kind1</button>
        <button onClick={() => { changeKind(2) }}>kind2</button>
      </div>
      <ProductCompo />
      <hr></hr>
      <h2>선택한 상품</h2>
      <CproductCompo />
      <div>
        <p>{state.ReserReducers.totalPrice.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}원</p>
      </div>
      <hr></hr>
      <h2>시간선택</h2>
      <hr></hr>
      <TimeTableCompo />
      <hr></hr>
      <PaymentCompo ref={paymentRef} />
      <button onClick={order}>예약 하기</button>
    </div>
  );
}

export default ReservationProPage;

자식 컴포넌트

import { forwardRef, useImperativeHandle, useRef } from "react";

function PaymentCompo(prop, ref) {
    const nameRef = useRef();
    const priceRef = useRef();
    const paymentIdRef = useRef();
    useImperativeHandle(ref, () => ({
        // 부모 컴포넌트에서 사용할 함수를 선언
        on_pay
    }))
    /**
     * name:"상품이름"
     * price:"결제가격"
     * paymentid:"주문번호"
     * @param {object} data 
     */
    function on_pay(data) {
        nameRef.current.value=data.name;
        priceRef.current.value=data.price;
        paymentIdRef.current.value=data.paymentid;
        var myform = document.mobileweb; 
        myform.action = "https://mobile.inicis.com/smart/payment/";
        myform.target = "_self";
        myform.submit(); 
    }
    return (
        <form name="mobileweb" method="post" accept-charset="euc-kr" hidden >
            <input type="text" name="P_NEXT_URL" value="http://localhost:8080/api/auth/payment" />
            <input type="text" name="P_INI_PAYMENT" value="CARD" />
            <input type="text" name="P_RESERVED" value="twotrs_isp=Y&block_isp=Y&twotrs_isp_noti=N" />
            <input type="text" name="P_MID" value="INIpayTest" />
            <input type="text" name="P_OID" ref={paymentIdRef} value="" />
            <input type="text" name="P_GOODS" ref={nameRef} value="" />
            <input type="text" name="P_AMT" ref={priceRef} value="" />
            <input type="text" name="P_UNAME" value="테스터" />
            <input type="text" name="P_NOTI_URL" value="" />
            <input type="text" name="P_HPP_METHOD" value="1" />
        </form>
    )
}
export default forwardRef(PaymentCompo);
<PaymentCompo ref={paymentRef} />
paymentRef.current.on_pay(data);

자식컴포넌트에 ref를 지정해주고 ref에서 꺼내서 쓰면된다

 

'React+Redux' 카테고리의 다른 글

리액트 env 사용하기  (0) 2023.01.21
리액트 레이아웃 적용하기  (0) 2023.01.21
React +Redux + ReduxTookit 툴킷이 답이다  (0) 2022.09.06