피그마 주소 입력 칸

피그마에서 보면 결제하기전에 이렇게 주소를 넣는 칸이 있었다. 

생각해보면 우리는 주문할때 항상 저기를 클릭하면 우편주소 검색하는 모달이 떠서

기억나는 길주소를 넣으면 기가막히게 우리 집 주소를 찾아주는 걸 알 것이다. 

 

일단 첫번째로 input을 클릭하면을 켜줘야하는 기능을 구현해야 했는데, 

어떻게 해줄까 생각을 하다가 useRef()를 사용해서 강제로 click을 하게끔 만들어 주자는 생각을 해봤다.

 

일단 useRef()를 만들어서 SearchTrigger라는 변수에 할당해줬다. 

 

 

 

 

 

박스 친 곳을 보면 Input을 onClick 할때, SearchTrigger.current.click()을 통해아래쪽 Button이 SearchTrigger의 당사자 이시니까 클릭이 자동으로 되시겠다. 근데 위쪽에 if문으로 열심히 타입가드 한답시고했는데, 필자가 타입스크립트를 정말 할 줄 몰라서 보기 좀 그럴 수도 있다. 제발 다른 방법이 있으면 알려주세요.. ㅠ 

 

 

 

 

 

 

 

자 이제 저 onClick에 무엇을 넣든 잘 실행될텐데, 이제 우편번호 검색을 해야하는데, 이미 그에 해당되는 라이브러리가 있었다. ㅎㅎ ; 

https://github.com/bernard-kms/react-daum-postcode

 

GitHub - bernard-kms/react-daum-postcode: 리액트 컴포넌트로 만든 Daum 우편번호 검색 서비스입니다.

리액트 컴포넌트로 만든 Daum 우편번호 검색 서비스입니다. Contribute to bernard-kms/react-daum-postcode development by creating an account on GitHub.

github.com

 

들어가보면 Embed랑 popup 이렇게 두가지 방법이 있는데, 

만약에 그냥 검색창만 조그맣게 window.open으로 띄우고 싶다면 예를 들면 

             이런식으로 하고 싶다면, popup 코드를 사용하면 된다. 굉장히 싶다.. 그냥 깃헙에 예제 코드 복붙해놓으면 되는데, 

 

const App = () => {

    // 함수 파라미터로 scriptUrl이 required인데 처음에 어딧는지 찾았는데, 
    // 깃헙에 링크타고 들어가면 있더라.. 
    const scriptUrl =
    'https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js';
  
     const open = useDaumPostcodePopup(scriptUrl);
     const handleComplete = (data: Address) => {
    	let fullAddress = data.address;
    	let extraAddress = '';

    	if (data.addressType === 'R') {
      	if (data.bname !== '') {
        	extraAddress += data.bname;
      	}
      	if (data.buildingName !== '') {
        	extraAddress +=
          	extraAddress !== '' ? `, ${data.buildingName}` : data.buildingName;
      	}
      	fullAddress += extraAddress !== '' ? ` (${extraAddress})` : '';
    }

    // 집주소 찾아서 확인 누르면 fullAddress에 주소 담겨서 나오는데, 
    // 나는 Input에 yup이 걸려있어서 setValue로 바로 넣어주었다. 
    setValue('address', fullAddress);
  };

  // 트리거 해줄 함수 
  const handleClick = () => {
    open({ onComplete: handleComplete });
  };
  
  	return (
      <button onClick={handlClick}>주소검색</button>
    );
  };

 

처음에는 이러고 끝내려고 했는데,  문제점이 몇가지 있었다. 아무래도 window 창 그 자체이다 보니 닫기버튼이 못생겼고, 모달처럼 overlay를 클릭한다고 close되는 것도 아니고, 클릭할때마다 중복해서 창이 켜지는 문제 등이 있었는데 물론 여러가지 이미 있는 props를 전달해서 커스텀해볼 수 있었지만 일단 모달이 더 이쁜거 같다.  그래서 그냥 모달안에 집어 넣기로 했다. 그런데 본인은 프로젝트 안에서 Chakra UI를 사용하고 있어서 사뭇 다를 수 있는데 그게 문제는 아니니 넘어가도록 하겠다. 

 

그렇게 되면 우리는 Embed를 사용해야하는데 뭐 크게 다르지 않다.

코드는 다 비슷하지만 Embed는 컴포넌트를 넘겨준다.  

그래서 이 컴포넌트를 나는 Modal Body에 쏘옥 넣어줬을뿐이다. 

 

혹시 몰라 그냥 코드도 첨부해보도록 하겠다. 

import React from 'react';
import DaumPostcodeEmbed, { Address } from 'react-daum-postcode';
import { UseFormSetValue } from 'react-hook-form/dist/types';

import {
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalHeader,
  ModalOverlay,
} from '@chakra-ui/react';

import { FormDataType } from '../_hooks/useFormValidate';

interface AddressModalProps {
  setValue: UseFormSetValue<FormDataType>;
  isOpen: boolean;
  onClose: () => void;
}

function AddressModal({
  isOpen,
  onClose,
  setValue,
  ...basisProps
}: AddressModalProps) {
  const handleComplete = (data: Address) => {
    let fullAddress = data.address;
    let extraAddress = '';

    if (data.addressType === 'R') {
      if (data.bname !== '') {
        extraAddress += data.bname;
      }
      if (data.buildingName !== '') {
        extraAddress +=
          extraAddress !== '' ? `, ${data.buildingName}` : data.buildingName;
      }
      fullAddress += extraAddress !== '' ? ` (${extraAddress})` : '';
    }
    setValue('address', fullAddress);
    onClose();
  };
  return (
    <Modal isOpen={isOpen} onClose={onClose} {...basisProps}>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>주소 검색</ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <DaumPostcodeEmbed onComplete={handleComplete} {...basisProps} />
        </ModalBody>
      </ModalContent>
    </Modal>
  );
}

export default AddressModal;

 

아 그리고 TypeScript를 사용하면 문서에서는 어딧는지 안알려준다. 그냥 node_module -> lib 따라 들어가서 찾도록 하자 ㅎㅎ..