트러블슈팅

[#1] 트러블 슈팅 (react)

작소율 2024. 4. 9. 21:47

 

1. 문제 상황 

 

서로 다른 두 페이지에서 같은 버튼을 사용해야하는 상황이였다.

 

 

 

wishList 부분에서 메이트 신청 버튼 부분과 restaurantList 부분에서 메이트 신청 버튼 부분에서 같은 폼으로 각 페이지에서 고른 Place의 정보를 넘겨주는 상황에서 문제 발생 

 

2.  어떤 문제인가..🫨

 

처음에는 위시리스트에서 메이트 신청 버튼 사용 상황을 생각하지 못하고, 맛집리스트에서 localStorage 를 이용해 place의 정보를 저장했었다.

const newPlaceData = {
                placeId: placeData.id,
                placeName: placeData.place_name,
                placeAddress: placeData.address_name,
                placeRoadAddress: placeData.road_address_name,
                placePhone: placeData.phone,
                placeUrl: placeData.place_url,
                placeLat: placeData.y,
                placeLng: placeData.x,
            };

localStorage.setItem('placeInfo', JSON.stringify(newPlaceData));
window.location.href = `/eatMate/mateForm?category=${category}`;

 

같은 방식으로 위시부분에서도 localStorage에 set 할까 했지만 메이트 폼에서 위시에서 온 place 정보인지 맛집에서 온 place 정보인지 구별해서 처리하는 것보다 각자 부분에서 선택한 place 정보를 보내주는 편이 유지보수 측면에서 나을듯하여 구글링과 챗지피티 검색 후 useNavigate 와 useLocation 을 이용해 데이터를 처리하기로 결정! 🔫

 

let navigate = useNavigate(); 
const handleClickMate = () => { 
	// navigate 함수를 사용하여 place 데이터와 함께 mateModal 경로로 이동 
    navigate('/mateModal', { state: { place: place } }); 
}; 

return ( <button onClick={handleClickMate}>메이트 찾기</button> );

 

import { useLocation } from 'react-router-dom';

function MateModal() {
  const location = useLocation();
  const { place } = location.state || {}; // state가 없는 경우를 대비한 기본값 설정

  console.log(place); // 여기에서 place 객체에 접근할 수 있습니다.

  // place 객체를 사용한 렌더링 또는 로직 구현...
  return (
    <div>
      {/* place 데이터를 활용한 UI 구성 */}
    </div>
  );
}

 

챗지피티가 알려준 방식대로 코드를 짰는데...

useNavigate 를 사용해 데이터를 전송하면 계속해서 

Cannot read properties of undefined (reading 'placeName')
TypeError: Cannot read properties of undefined (reading 'placeName')
    at MateModal (http://localhost:3000/main.a700f1324c57a9f24fe0.hot-update.js:221:31)

 

ERROR
"undefined" is not valid JSON
SyntaxError: "undefined" is not valid JSON
    at JSON.parse (<anonymous>)
    at MateModal (http://localhost:3000/main.5b1a571147ea2585727f.hot-update.js:78:26)
    at renderWithHooks (http://localhost:3000/static/js/bundle.js:96408:22)
    at updateFunctionComponent (http://localhost:3000/static/js/bundle.js:99288:24)
    at beginWork (http://localhost:3000/static/js/bundle.js:101000:20)
    at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:86004:18)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:86048:20)
    at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:86105:35)
    at beginWork$1 (http://localhost:3000/static/js/bundle.js:105969:11)
    at performUnitOfWork (http://localhost:3000/static/js/bundle.js:105217:16)

 

이동한 페이지에서 해당 객체를 찾으면 계속 undefined 관한 오류가 떴다..

 

3. 문제 해결 ing ⛏️..⛏️...

 

 

계속 객체의 형태를 바꾸고 이름을 바꾸고 별 난리를 쳤는데

알고보니 const { place } = location.state;

{} 중괄호를 감싸고 받아서 안 받아지는거였다..;;

 

리액트(React)에서 중괄호 {}를 사용하여 변수를 감싸는 것은 JSX 내에서 JavaScript 표현식을 사용하고자 할 때 필요합니다. JSX는 HTML과 비슷한 문법을 사용하지만, 실제로는 JavaScript를 확장한 것이기 때문에, JavaScript 표현식을 사용하려면 중괄호를 사용해야 합니다.

 

챗지피티만 맹신했다가 계속 삽질을 하고 있었던 것 .. 😑


useNavigate 

useNavigate Hook 은 네비게이션 함수를 반환한다. 이 함수를 사용하여 애플리케이션 내에서 다른 경로로 이동하거나, 현재 경로를 대체하거나, 이전 페이지로 돌아가는 등의 네비게이션 작업을 수행할 수 있다.

 

부모에서 자식, 자식에서 부모로 값을 전달하는 상황은 보통 props로 해결이 된다.

그러나 페이지를 이동하면서 값을 전달해야하는 상황은 부모와 자식의 관계가 아니기 때문에 다른 방법으로 해결해야한다.

바로 기존 페이지에서 useNavigate()*로 값을 전달하고, 새로운 페이지에서 useLocation()으로 값을 받아오는 방법이다.

 

* React-dom-router v6 기준

useLocation

useLocation Hook은 현재 페이지의 URL 정보를 담고 있는 객체를 반환한다. 이 객체는 pathname, search, hash, state 등 여러 속성을 포함하고 있으며, useNavigate를 통해 전달된 state는 useLocation 를 통해 사용할 수 있다.

 

useNavigate 사용법

먼저, react-router-dom 패키지를 설치해야 한다.

npm install react-router-dom --save

 

useNavigate 는 state 옵션을 사용해서 네비게이션 대상 페이지에 상태(state)를 보낼 수 있다.

state 키의 값으로는 전달하고자 하는 상태(객체, 문자열, 숫자 등 어떤 자바스크립트 데이터도 가능)를 지정한 뒤 네비게이션 대상 페이지에서는 useLocation 훅을 사용하여 이 상태를 받아올 수 있다.

 

예시를 통해 useNavigation 과 useLocation 의 사용법을 알아보자 🔦

import React from 'react';
import { useNavigate } from 'react-router-dom';

function LoginPage() {
  const navigate = useNavigate();

  function handleLoginSuccess() {
    navigate('/dashboard', { state: { from: 'login' } });
  }

  return (
    <div>
      {/* 로그인 로직 */}
      <button onClick={handleLoginSuccess}>Login</button>
    </div>
  );
}

 

 

navigate 함수를 통해 path (이동하는 페이지 경로 값) 와 전달할 데이터 값을 설정해준다.

from 이라는 key 값으로 'login' 이라는 문자열을 담아줬다. 

 

import React from 'react';
import { useLocation } from 'react-router-dom';

function Dashboard() {
  const location = useLocation();
  const fromLogin = location.state?.from === 'login';

  return (
    <div>
      {fromLogin && <p>Welcome back! You just logged in.</p>}
      {/* 대시보드 컨텐츠 */}
    </div>
  );
}

 

이동한 페이지에서 useLocation 함수를 이용해 state에서 key 값을 통해 값을 얻어올 수 있다.

 

    let navigate = useNavigate();

    const handleClickMate = (place) => {

        // 필요한 place 데이터를 mateModal 경로로 전달
        navigate(`/eatMate/mateForm?category=${category}`, { state: {place: place}});
    };

 

    const location = useLocation();
    console.log(typeof location.state);
    console.log(location.state);

    const placeInfo = location.state.place

 

이렇게 바꿨더니 잘 받아졌다 ㅎㅎ!

앞으론 맹신하지말고 구글링 잘 하고 정확히 잘 알아봐야겠다.. 🥺

'트러블슈팅' 카테고리의 다른 글

[mac] ora-01033: oracle initialization or shutdown in progress  (0) 2024.05.08
[#0] 트러블슈팅  (0) 2024.04.09