FRONTENDSCHOOL6 / ready-act

멋쟁이사자처럼 파이널프로젝트 16조
MIT License
0 stars 4 forks source link

[R09M App] CreateRoom 페이지 - Kakao Map 에서 value 값을 기억해야할때 value={data}의 위치 이슈 #53

Closed jellyjoji closed 9 months ago

jellyjoji commented 9 months ago

내용

Kakao Map 에서 찍은 주소값을 updateCreateRoomForm 에 pickUp 항목으로 저장시켰습니다, 해당 페이지를 벗어나도 vlaue 값이 기억되도록 useState(value) 를 주고 value=createRoomForm.meetingPoint} 를 CreateRoom 의 MeetingPorint컴포넌트에 적용시켰습니다. value 값을 기억해야할때 를 적용시킬 속성의 위치가 여기가 맞을까요 ? (굵은 글자 표시)

<div className="hAddr flex">
          {/* 여기 */}
          <span readOnly value={data || ""} id="centerAddr" className='p-4'>
            {data}
          </span>

Location.jsx 의 전체 코드를 공유합니다.

import arrowLeft from '@/assets/icons/arrowLeft.svg';
import { useContext, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import './Location.module.css';
import { AppContext } from '@/App';
import Button from "../../components/Button";

const { kakao } = window;

function Location({ value }) {
  const { updateCreateRoomForm } = useContext(AppContext);

  const [data, setData] = useState(value);

  useEffect(() => {
    const mapContainer = document.getElementById('map'), // 지도를 표시할 div
      mapOption = {
        center: new kakao.maps.LatLng(37.57157200866145, 126.9763416696016), // 지도의 중심좌표
        level: 4,
      };

    const map = new kakao.maps.Map(mapContainer, mapOption);

    const geocoder = new kakao.maps.services.Geocoder();

    const marker = new kakao.maps.Marker(),
      infowindow = new kakao.maps.InfoWindow({ zindex: 1 });

    searchAddrFromCoords(map.getCenter(), displayCenterInfo);

    kakao.maps.event.addListener(map, 'click', function (mouseEvent) {
      searchDetailAddrFromCoords(mouseEvent.latLng, function (result, status) {
        if (status === kakao.maps.services.Status.OK) {
          let detailAddr = !!result[0].address.address_name
            ? result[0].address.address_name
            : '위치정보를 불러올수없음';
          setData(detailAddr);

          const content = '<div className="bAddr">' + detailAddr + '</div>';

          marker.setPosition(mouseEvent.latLng);
          marker.setMap(map);

          infowindow.setContent(content);
          infowindow.open(map, marker);
        }
      });
    });

    kakao.maps.event.addListener(map, 'idle', function () {
      searchAddrFromCoords(map.getCenter(), displayCenterInfo);
    });

    function searchAddrFromCoords(coords, callback) {
      geocoder.coord2RegionCode(coords.getLng(), coords.getLat(), callback);
    }

    function searchDetailAddrFromCoords(coords, callback) {
      geocoder.coord2Address(coords.getLng(), coords.getLat(), callback);
    }

    function displayCenterInfo(result, status) {
      if (status === kakao.maps.services.Status.OK) {
        const infoDiv = document.getElementById('centerAddr');

        for (let i = 0; i < result.length; i++) {
          if (result[i].region_type === 'H') {
            infoDiv.innerHTML = result[i].address_name;
            break;
          }
        }
      }
    }
  }, []);

  useEffect(() => {
    updateCreateRoomForm('meetingPoint', data);

  }, [data]);

  return (
    <div className="h-full">
      <div className="relative h-12">
        <p className="text-center py-3">지도에서 위치 확인</p>

        <Link to="/createroom">
          <img src={arrowLeft} alt="뒤로 가기" className="absolute top-3" />
        </Link>
      </div>

      <div className="map_wrap">
        <div id="map" className="w-full h-[420px]"></div>
        <div className="hAddr flex">
          {/* <input readOnly value={data || ""} id="centerAddr" className='p-4' /> */}
          <span id="centerAddr" className='p-4'>
            {data}
          </span>

          <Link to="/createroom" className="bg-white w-full absolute max-w-xl bottom-0 p-4 drop-shadow-2xl">
            <Button type="submit" className="activeButton lgFontButton w-full ">
              이 위치로 설정
            </Button>
          </Link>

        </div>
      </div>
    </div>
  );
}

export default Location;

※ 댓글에 이슈 해결 완료 후 결과 또는 해결 과정 이미지 첨부

jellyjoji commented 9 months ago

페이지가 전환되면 컴포넌트는 언마운트 됩니다.

Location 컴포넌트의 아래 useEffect 훅 함수는 data 상태가 변경된 이후 다음 렌더링에서 실행됩니다. 하지만 페이지가 전환되면 Location 컴포넌트가 언마운트(unmount)되므로 함수는 실행되지 않습니다.

즉, 아래처럼 코드를 작성하면 안됩니다.

// ❌ 아래처럼 코드를 작성하면 안됩니다.

// useEffect(() => {
//  updateCreateRoomForm('meetingPoint', data);
// }, [data]);

카카오 지도를 사용자가 클릭할 때 상태 저장을 요청합니다.

useEffect 훅 내부의 Kakao 지도 API의 클릭 이벤트 핸들러 내부에서 Location 컴포넌트의 상태 업데이트 요청할 때, 앱의 전역 상태 또한 업데이트 요청하세요. 로컬 상태는 Location 페이지 컴포넌트에서 화면에 렌더링 할 주소 정보이고, 앱 상태인 폼 데이터는 CreateRoom 페이지 컴포넌트에서 기억되어 사용될 주소 정보입니다.

kakao.maps.event.addListener(map, 'click', function (mouseEvent) {
  searchDetailAddrFromCoords(mouseEvent.latLng, function (result, status) {
    if (status === kakao.maps.services.Status.OK) {
      let detailAddr = !!result[0].address.address_name
        ? result[0].address.address_name
        : '위치정보를 불러올수없음';

            // Location 컴포넌트 상태 업데이트
      setData(detailAddr);
      // 앱 상태(전역, 페이지 전환 시에도 기억 됨) 업데이트
            **updateCreateRoomForm('meetingPoint', detailAddr);**

      const content = '<div className="bAddr">' + detailAddr + '</div>';

      marker.setPosition(mouseEvent.latLng);
      marker.setMap(map);

      infowindow.setContent(content);
      infowindow.open(map, marker);
    }
  });
});