본문 바로가기

TIL

[TIL-123] 위코드 23일차: React Router & Sass

ReactJS

 

 

props

개념

properties라는 뜻으로, 함수형 컴포넌트에 객체를 인자로 전달해서 함수 안에서 변수처럼 사용할 수 있다.

 

응용

  <div class="profile">
    <img alt="달님이 프사" src="img/달님.jpeg" />
    <div class="profileRow">
      <p>dal_nim</p>
      <p class="grayText">10분 전</p>
    </div>
  </div>

  <div class="profile follow">
    <div class="followRow">
      <img alt="별님이 프사" src="img/별님.jpeg" />
      <div class="ComponentRow">
        <p>byeol_nim</p>
        <p class="grayText">hae_dal_byeol님 외...</p>
      </div>
    </div>
    <span class="blueSpan">팔로우</span>
  </div>

[문제상황] 유사한 구조의 두 profile <div>를 컴포넌트로 바꾸었다. 그런데 서로 다른 텍스트가 들어가거나 태그가 필요할 때 그런 점들을 구현하기 힘들다.

  1. <img> 속성 : alt와 src 속성의 값을 상황에 따라 바꾸어야 한다. 어려운 점은 텍스트 형식에 props와 일반 텍스트를 결합해야 한다는 점이다. 
  2. <p> 태그의 content : 상황에 따라 user의 닉네임을 props로 받아서 담아야 한다.
  3. <span> 태그 : 팔로우 버튼이 필요한 경우에만 포함되어야 한다.
  4. style을 위한 클래스 : 두번째 profile <div>에 다른 스타일을 적용시킬 때 "follow" 클래스를 사용해서 css를 썼는데 간결한 첫번째 profile <div>를 기준으로 컴포넌트를 만들어서 사라졌다. css 암만 써도 왜 안되나 했네ㅠㅠㅠ

 

<Box name={"달님"} userId={"dal_nim"} isFollow={0} />
<Box name={"별님"} userId={"byeol_nim"} isFollow={1} />

function Box({ name, userId, isFollow }) {
  return (
    <div className="boxComponent">
      <div className="boxLabel">
        <span className="grayText">스토리</span>
        <span>모두 보기</span>
      </div>
      <Profile name={name} userId={userId} isFollow={isFollow} />
      <Profile name={name} userId={userId} isFollow={isFollow} />
      <Profile name={name} userId={userId} isFollow={isFollow} />
      <Profile name={name} userId={userId} isFollow={isFollow} />
    </div>
  );
}

function Profile({ name, userId, isFollow }) {
  return (
    <div className="profile">
      <img style={isFollow === 1 ? { border: "none" } : {}} alt={`${name}이 프사`} src={`../../../../images/${name}.jpeg`} />
      <div className="profileRow">
        <p>{userId}</p>
        <p className="grayText">
          {isFollow === 0 ? "10분 전" : "hae_dal_byeol님이 팔로우합니다"}
        </p>
      </div>
      <span className="blueSpan" style={isFollow === 0 ? { display: "none" } : {}}>팔로우</span>
    </div>
  );
}

[해결]

  1. src이나 alt 속성의 값 등, 텍스트 값이 들어갈 자리에 props와 문자열을 섞어서 작성하고 싶으면 자바스크립트 문법인 백틱과 ${props} 형태로 입력한다. 주의할 점은, 자바스크립트를 쓰는 거기 때문에 {} 안에 해당 코드를 담아줘야 한다.
  2. props를 받아서 {userId}의 형태로 입력했다.
  3. isFollow라는 props를 받아서 삼항조건연산자를 사용하여 값이 0일 때 화면에서 숨기도록 했다.
    • style 속성의 값은 객체로 전달하며, 그 안에서 css 속성은 key가 되고 camelCase를 따른다. 각 속성의 값은 value가 되며, 문자열로 "" 따옴표를 써야 한다.
  4. isFollow를 이용해서 두 profile <div>의 차이를 만들어줬다. css에서 사용했던 클래스도 <span>에 다시 넣어줬다.

 

느낀점

  • props가 헷갈리는 점은, 열어보면 객체인데 그 안을 채워줄 때 원래 알고 있던 property의 모양이 아니라 html 태그의 attribute 모양과 같기 때문인 것 같다. props를 보낼 때도, 받을 때도, console에 찍어보지 않으면 어떻게 생겼는지 눈으로 확인해볼 수 없기도 하다.
  • 그런데 props가 객체라는 점을 유념하고서, 보낼 때나 받을 때나 항상 key와 value가 무엇인지에 집중하면 덜 헷갈리는 것 같다. Comment, Article, Profile 컴포넌트 안에 props를 보내고 받으면서 많이 훈련이 됐다.

 

 

 

useNavigate와 <Link /> 

개념

다른 페이지로 이동할 때 useNavigate와 <Link /> 두 가지를 사용할 수 있다.

<Link />는 리액트에 이미 만들어져있는 컴포넌트로, 다른 컴포넌트와 같은 방식으로 사용하면 된다. 기능은 html의 <a> 태그와 거의 같다. html로 변환되면 실제로 <a> 태그가 된다. 하지만 <a> 태그와의 차이는, <a> 태그는 보통 프로젝트 외부 사이트로 이동할 때 쓰고 <Link /> 컴포넌트는 프로젝트 내의 다른 페이지로 이동할 때 쓴다는 점이다.

useNavigate는 페이지를 이동시켜주는 함수를 만드는 훅(hook)이다. 만들어진 함수에 path(이동할 페이지 경로)를 인자로 넘겨주면 이동된다.

 

차이

<Link />는 <a> 태그와 거의 같기 때문에 누르면 정해진 페이지로 바로 이동한다. 하지만 useNavigate는 javascript 코드기 때문에 조건문 등을 이용해서 특정 상황에만 이동시킨다든지 다양한 기능을 구현할 수 있다.

 

Link 사용법

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

<Link to="/main">Main</Link>

href 속성에 url 주소를 쓰는 <a> 태그와 달리, to 속성에 이동할 페이지의 url 주소를 입력한다.

 

useNavigate 사용법

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

function Login() {
  const navigator = useNavigate();

  const goToMain = () => {
    navigator("/main");
  };

  return (
    <main className="loginMain">
      <div className="login">
        <h1>Westagram</h1>
        <form className="loginForm">
          <input placeholder="전화번호, 사용자 이름 또는 이메일"></input>
          <input type="password" placeholder="비밀번호" />
          <button disabled onClick={goToMain}>
            로그인
          </button>
        </form>
        <a href="">비밀번호를 잊으셨나요?</a>
      </div>
    </main>
  );
}
  1. 리액트 라우터 돔 모듈에 들어있는 useNavigate 기능을 사용하기 위해 import한다.
  2. const navigator = useNavigate();
    => 변수에 useNavigate()를 불러와 할당한다.
    • [질문] 왜 useNavigate()를 그냥 쓸 수 없고 변수에 할당하는가??
    • 훅의 하나로, useNavigate 훅을 실행하면 페이지를 이동할 수 있게 해주는 함수를 반환한다. 훅의 사용법이 그렇기 때문이라고 생각하면 될 것 같다.
  3. navigator("/page");
    => 사용할 이벤트리스너 함수 안에서 실행한다.

 

[주의사항]

  • import할 때 { useNavigate }의 중괄호를 빼먹으면 오류가 난다.
  • event listener 함수는 함수명에 () 괄호를 붙이면 안 된다. 괄호를 붙였더니 페이지가 로드되자마자 해당 함수가 미친듯이 실행됐다.

 

 


<공부할 것>

 

 

@use

개념

아직 몰겠음.

 

참고

[Sass/SCSS] At Rules - @use https://jiineeee.tistory.com/23