2차 프로젝트 회고 (ActivatedNav)

기본 Nav 에 이어서 활성화된 Nav 를 회고한다.


활성화된 Nav (ActivatedNav.js)

import { useNavigate } from 'react-router-dom';
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import Person from './Person';
import { FaSearch } from 'react-icons/fa';

function SearchNav({ setIsClickedNav, isClickedNav }) {
  const [whichIsClicked, setWhichIsClicked] = useState('');
  const [personCardData, setPersonCardData] = useState([]);
  const [searchLocation, setSerchLocation] = useState('');
  const [checkInDate, setCheckInDate] = useState('');
  const [checkOutDate, setCheckOutDate] = useState('');
  const [personNum, setPersonNum] = useState(0);
  const [childNum, setChildNum] = useState(0);
  const navigate = useNavigate();

  useEffect(() => {
    fetch('data/PersonData.json')
      .then(res => res.json())
      .then(data => {
        setPersonCardData(data);
      });
  }, []);
  

  // useEffect (side effect) 에서 fetch 함수로 목데이터 PersonData.json 파일을 불러와 
  // 초기 state 인 personCardData 이름의 빈 배열안에 업데이트 한다
  
  const goToListPage = () => {
    if (!searchLocation) {
      alert('장소를 입력해주세요');
      return;
    } else if (!checkInDate) {
      alert('체크인 날짜를 입력해주세요');
      return;
    } else if (!checkOutDate) {
      alert('체크아웃 날짜를 입력해주세요');
      return;
    } else if (!personNum + childNum) {
      alert('인원을 선택해주세요');
      return;
    }

    setWhichIsClicked('ㅇ');

    navigate(
      `roomlist?location=${searchLocation}&check_in=${checkInDate}&check_out=${checkOutDate}&guest=${
        personNum + childNum
      }`
    );
  };

  const userSelectThis = buttonName => {
    setWhichIsClicked(buttonName);
  };

  const plusPersonNumber = title => {
    if (title === '성인') {
      setPersonNum(personNum + 1);
    } else if (title === '어린이') {
      setChildNum(childNum + 1);
    }
  };

  const minusPersonNumber = title => {
    if (title === '성인') {
      setPersonNum(personNum - 1);
    } else if (title === '어린이') {
      setChildNum(childNum - 1);
    }
  };

  const changeLocationInput = e => {
    if (e.target.name === 'location') {
      setSerchLocation(e.target.value);
    } else if (e.target.name === 'checkIn') {
      setCheckInDate(e.target.value);
    } else if (e.target.name === 'checkOut') {
      setCheckOutDate(e.target.value);
    }
  };

  return (
    <Navigation>
      <Room>
        <div className="text">숙소</div>
      </Room>
      <SearchBarContainer>
        <SearchBar type="button">
          <Location
            whichIsClicked={whichIsClicked}
            onClick={() => userSelectThis('location')}
          >
            //onClick시 userSelectThis 함수를 실행해 setWhichIsClicked의 인자를 location으로 업데이트해서
            // whichIsClicked가 location이 된다 (whichIsClicked={whichIsClicked})
            <LocationDiv>
              <LocationText>위치</LocationText>
              <LocationInput
                placeholder="어디로 여행가세요?"
                value={searchLocation}
                onChange={changeLocationInput}
                name="location"
              />
// LocationInput 의 value 값은 searchLocation 의 상태값으로 설정하고
// onChange event 로 ChangeLocationInput 함수를 실행한다
// ChangeLocationInput 함수의 기능은 e.target.name이 
// location 인지 checkIn 인지 CheckOut 인지에 따라 각각의 초기 상태값들을 
// e.target.value 값으로 업데이트 한다                  
            </LocationDiv>
          </Location>
          <CheckIn
            whichIsClicked={whichIsClicked}
            onClick={() => userSelectThis('checkIn')}
          >
            //onClick시 userSelectThis 함수를 실행해 setWhichIsClicked의 인자를 checkIn 으로 업데이트해서
            // whichIsClicked가 checkIn 이 된다 (whichIsClicked={whichIsClicked})
            <CheckInDiv>
              <CheckInText>체크인</CheckInText>
              <CheckInInput
                placeholder="날짜입력"
                value={checkInDate}
                onChange={changeLocationInput}
                name="checkIn"
              />
                  // value는 checkInDate 의 초기상태값은 공백으로 설정한다
                  // onChange 이벤트로 changeLocationInput 을 실행시켜 e.target.name 값에 따라 각 input 의 value 값을 업데이트한다
            </CheckInDiv>
          </CheckIn>
          <CheckOut
            whichIsClicked={whichIsClicked}
            onClick={() => userSelectThis('checkOut')}
          >
            //onClick시 userSelectThis 함수를 실행해 setWhichIsClicked의 인자를 checkOut 으로 업데이트해서
            // whichIsClicked가 checkOut 이 된다 (whichIsClicked={whichIsClicked})
            <CheckOutDiv>
              <CheckOutText>체크아웃</CheckOutText>
              <CheckOutInput
                placeholder="날짜 입력"
                value={checkOutDate}
                onChange={changeLocationInput}
                name="checkOut"
              />
                  // value는 checkOutDate 의 초기상태값은 공백으로 설정한다
                  // onChange 이벤트로 changeLocationInput 을 실행시켜 e.target.name 값에 따라 각 input 의 value 값을 업데이트한다
            </CheckOutDiv>
          </CheckOut>

          <PersonNum whichIsClicked={whichIsClicked}>
            <PersonDiv onClick={() => userSelectThis('personNum')}>
               //onClick시 userSelectThis 함수를 실행해 setWhichIsClicked의 인자를 personNum 으로 업데이트해서
            // whichIsClicked가 personNum 이 된다 (whichIsClicked={whichIsClicked})
              <PersonText>인원</PersonText>
              <PersonInput>
                {personNum + childNum > 0
                  ? `게스트 ${personNum + childNum}`
                  : '게스트 추가'}
// personNum, childNum 을 더한 상태값이 0보다 크면 '게스트 (성인 + 어린이) 명' 으로 렌더링하고
// 아닐경우 '게스트 추가' 로 렌더링한다
              </PersonInput>
            </PersonDiv>
            <MapContainer>
              {whichIsClicked === 'personNum' &&
                personCardData.map(card => {
                  return (
                    <Person
                      key={card.id}
                      id={card.id}
                      title={card.title}
                      subtitle={card.subTitle}
                      backgroundcolor={card.backgroundcolor}
                      personNum={personNum}
                      childNum={childNum}
                      plusPersonNumber={plusPersonNumber}
                      minusPersonNumber={minusPersonNumber}
                    />
                  );
                })}
// whichIsClicked 값이 personNum 이고 personCardData.map 의 값이 있다면
// 자식 컴포넌트 Person.js 에게 물려준 key, id, title, subtitle, backgroundcolor, 속성값들과
// personNum, childNum, 상태값들과
// plusPersonNumver, minusPersonNumber 함수들을 props 로 넘겨주고
// import 해서 가져온 자식 컴포넌트 Person.js를 id 별로 전달된 속성값, 상태값, 함수들을 가져와서 map 메서드로 인원수 부분을 렌더링 한다  

            </MapContainer>
            <SearchZoom
              type="button"
              onClick={() => {
                return goToListPage(), setIsClickedNav(!isClickedNav);
              }}
            >
// 검색버튼 클릭시 gotolistpage 함수를 실행시켜 각 input 의 상태값들이
// 공백이면 alert 창을 띄우고
// Nav.js 컴포넌트에서 물려받은 setisClickednav(!isClickednav) 함수를 실행시켜
// isClickedNav 초기상태값인 false 를 true 로 업데이트해서 Activated된 Nav를 비활성화시킨다

// 만약 각 input 의 상태값이 true 라면 setWhichIsClicked('ㅇ') 함수를 실행시켜
// whichIsClicked 의 공백인 상태값을 'ㅇ' 으로 업데이트해서 각 input 창의 onClick event의 함수인 
// userSelectThis 를 실행하지 못하도록 한다 ( location 도 checkIn, checkOut 도 personNum 도 아닌 'ㅇ' 으로 바꿔줌으로써 )
// 그리고 roomlist 페이지로 이동하면서 쿼리파라미터로 위치값, 체크인 날짜값, 체크아웃 날짜값, 게스트 수의 상태값들을 전달한다
// (이 정보들을 가지고 roomlist 페이지에서 필터링된 데이터들을 볼 수 있다)
              <FaSearch className="search" />
            </SearchZoom>
          </PersonNum>
        </SearchBar>
      </SearchBarContainer>
    </Navigation>
  );
}


PersonData.json

[
  {
    "id": 1,
    "title": "성인",
    "subTitle": "만 13세 이상",
    "backgroundcolor": "rgb(217, 59, 48)"
  },
  {
    "id": 2,
    "title": "어린이",
    "subTitle": "만 2~12세",
    "backgroundcolor": "rgb(217, 59, 48)"
  }
]


Person.js (인원수 설정하는 컴포넌트)

function PersonCard({
  title,
  subtitle,
  backgroundcolor,
  personNum,
  childNum,
  plusPersonNumber,
  minusPersonNumber,
}) {
  return (
    <Container backgroundcolor={backgroundcolor}>
      <Text>{title}</Text>
      <SubText>{subtitle}</SubText>
      <PlusMinusContainer>
        <Minus
          value="minusBtn"
          onClick={() => minusPersonNumber(title)}
          disabled={personNum < 1 ? true : childNum < 1 ? true : false}
        >
// onclick event 로 부모로부터 물려받은 minusPersonNumber 함수를 실행하고 title 을 인자로 가진다
// minusPersonNumber 함수의 기능은 title 이 '성인'이라면 personNum 상태값을
// -1 해서 업데이트하고 title 이 '어린이'라면 childNum 상태값을 -1 해서 업데이트한다 
// personNum과 childNum의 상태값이 1보다 작으면 버튼이 비활성화가 된다       
          <MinusSpan>-</MinusSpan>
        </Minus>
        <Count>{title === '성인' ? personNum : childNum}</Count>
// title 상태값이 '성인'인지 아닌지에 따라서 <Count> 태그의 값이 적용된다 (성인 or 어린이)
	<Plus value="plusBtn" onClick={() => plusPersonNumber(title)}>
// onclick event 로 부모로부터 물려받은 plusPersonNumber 함수를 실행하고 title 을 인자로 가진다
// plusPersonNumber 함수의 기능은 title 이 '성인'이라면 personNum 상태값을
// +1 해서 업데이트하고 title 이 '어린이'라면 childNum 상태값을 +1 해서 업데이트한다 
           
          <PlusSpan>+</PlusSpan>
        </Plus>
      </PlusMinusContainer>
    </Container>
  );
}

// 부모 컴포넌트로부터 물려받은 속성값들을 가지고 부모 컴포넌트 (ActivatedNav.js) 에서 하나씩 렌더링된다



LoginPop.js (로그인버튼 클릭시 나오는 컴포넌트)
import React from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';

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

  const LogOutUser = e => {
    navigate('/');
  };

  return (
    <LoginPop>
      <Mypage onClick={() => navigate('mypage')}>마이페이지</Mypage>
// onClick 이벤트가 발생할때마다 navigate 함수를 실행시키는데 인자로 'mypage'를 가진다
// 즉 mypage 주소로 이동한다
      <Logout onClick={LogOutUser}>로그아웃</Logout>
    </LoginPop>
// onClick 이벤트로 LogOutUser 함수가 실행되서 / (메인페이지) 주소로 이동한다
  );
}




시현 영상 : https://www.youtube.com/watch?v=J1Jll-h7MRE
깃헙 주소 : https://github.com/wecode-bootcamp-korea/26-2nd-WeAreBnB-frontend

좋은 웹페이지 즐겨찾기