위코드-TIL-17-react-위스타 (router, scss)

jin_sk·2020년 6월 15일
0

위코드

목록 보기
40/49

router

라우팅(Routing)이란 다른 주소에 따라 다른 뷰(화면)를 보여주는 기능
리액트 자체적으로는 이러한 기능이 내장되어있지 않다
(리액트가 Framework가 아닌 Library로 분류되는 이유)
React-router는 React의 라우팅 기능을 위해 가장 많이 사용되는 라이브러리이다
(여러 페이지를 url에 따라 로드하고싶을때 router를 사용)


react-router 설치

npm install react-router-dom --save

설치가 완료되면 package.json에 다음과 같이 생성된 것을 확인할 수 있다


Routes component 구현하기

Routes.js 파일을 생성해 component를 구현한다

코드

import React from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch,
} from 'react-router-dom';
import Login from './Pages/Login/Login';
import Main from './Pages/Main/Main';

class Routes extends React.Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={Login} />
          <Route exact path="/main" component={Main} />
        </Switch>
      </Router>
    )
  }
}

export default Routes;
  • React'react'에서 import 하기
    (react 사용을 위해)

  • BrowserRouter as Router, Route, Switch'react-router-dom'에서 import 하기
    (router 사용을 위해)

  • 페이지를 로드해줄 Login, Main component를 각각의 경로에서 import 해주기

  • class component 생성

    1. Router 태그 안에
    2. Switch 태그 안에
    3. 경로를 삽입한다
    4. 양식은 <Route exact path="경로" component={로드할 component} />
    5. 로그인 페이지는 경로를 /로 지정하였고
    6. 메인은 페이지 경로를 /main으로 지정하였다
    7. 위에 적어준 태그를 닫아준다

react-router index.js 에서 사용하기

설치후 index.js 에 router을 사용할 수 있도록 생성한 Routs.js파일을 import 하고
ReactDOM.render에 Routes component 를 넣어준다

코드

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Routes from "./Routes"


ReactDOM.render(
  <Routes />,
  document.getElementById('root')
);

Route 이동하기

Route 이동하는 방법은 두 가지가 있는데, 각 용도에 맞춰서 적절히 사용해야 한다

<a>와 같다 (dom에서 <a> 로 변환된다, a태그를 사용하고 싶지 않다면 Link를 사용하지 않아도 된다)
Link component를 사용하면 별다른 제약없이 바로 이동한다

1. 먼저 Login 파일을 Main 파일과 연력하려는 것이니 Login 파일에 아래와 같이 import하고

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

2. 버튼 태그 전체에 걸어준다 (버튼 태그 안 내용에 걸어줄 수 있지만 태그 자체에 걸어주는 것이 좋다)

<Link to="/main">   
  <button 
  	className={this.changeHandlerBgColor()}
  >
  	로그인
  </button>
</Link>

export default Login;

withRouter HOC 사용

Link를 사용하지 않고, 요소에 onClick 이벤트를 달아서 이동하고 싶은 곳으로 넘기는 방법도 있다
이벤트를 구현해서 this.propshistory에 접근해서 이동할 수 있다

받은 historypush 메서드에 이동할 path를 인자로 넘겨주면,
해당 Route로 이동할 수 있다

1. 먼저 아래와 같이 withRouter'react-router-dom' 을 import 해준다

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

2-1. withRouter 사용을 위한 함수를 만든다
그냥 외우자.. this.props.history.push('Route.js 파일에 만든 이동 주소');

goToMainup() {
	this.props.history.push('/main');
}

2-2. 조건 추가해보기
사용자가 입력한 id에 @, .com, .kr 포함 pw 5자 이상 이어야 main페이지로 넘어갈 수 있게 구현
일단은 되는지 확인이 필요..

  1. 기존 있던거에서 일단은 기능 구현이 되는지 확인하기 위해constructor의 state에 새로운 변수 추가
    constructor() {    
        super();

        this.state = {
            userInputId: "",
            userInputPw: "",
            btnChangeId: "",
            btnChangePw: "",
            idCheck: ""
        };
    }
  1. goToMainup() 에 조건 추가
    goToMainup() {
        //this.props.history.push('/main');
        if (this.state.btnChangeId && this.state.btnChangePw && this.state.idCheck) {
            this.props.history.push('/main');
        } else {
            alert('로그인 조건에 맞지 않습니다. 다시 확인해주세요')
        } 
    }
  1. 확인 (조건이 틀리면 Main으로 이동되지 않는다)

3. withRouter 사용을 위한 onClick 이벤트를 버튼 태그 안에 구현해준다
bind(this)thisLogin component라는 것을 확실하게 명시해주기 위해 사용
단어 사전적 의미로 묶어준다고 생각하면 될 것 같다..속해있는 component에

 <button 
  className={this.changeHandlerBgColor()}
  onClick={this.goToMainup.bind(this)}
>
  로그인
</button>

여기서 bind(this)는 이벤트를 bind 하는 부분이다
왜 이벤트를 bind 할까?
이걸 하지 않으면 render 메서드에서 this.goToMainup 함수를 호출했을 때,
함수의 this가 windowundefined가 되어버린다
그래서 this가 속해있는 컴포넌트 임을 명확하게 하기 위해 bind(this)를 사용해야 한다

참고 자료 : 제로초님 블로그

4. export 하는 class 부분을 withRouter로 감싼다
withRouter같이 해당 컴포넌트를 감싸주는 것을 HOC(higher-order component) 이라 한다
HOC는 react 고급 기능이며, 컴포넌트의 공통부분을 구현하는 패턴이라고 생각하면 된다
간단히 말해 HOC는 함수이며, 컴포넌트를 인자로 받고, 컴포넌트를 return하는 함수 이다

참고자료 : 공식문서 HOC

export default withRouter(Login);

화면

주소부분 확인


SCSS / SASS

  • 공식문서 : Sass

  • 설치 : npm install sass --save

css파일을 scss 파일로 바꿔주기

Login.js / Main.js 파일도 확장자를 바꿔줘야 한다

// Login.js 파일에서
import './Login.scss';

// Main.js 파일에서
import './Main.scss';

태그 전체에 CSS 속성을 주지말자...

태그 전체에 CSS 속성을 부여하면 전역(global)이 되어 전체 scss 파일에 적용이 된다
클래스 이름이 같아도 마찬가지다

처음에 css가 깨져 왜그런가 했더니 태그자체에 css속성을 받아와서 문제가 발생하였다

1. 로그인 버튼 수정

Login.js 에서 button 태그 자체에 scss 속성을 걸었더니
Main.js의 button 태그가 Login의 scss를 상속하여
Login.js의 button 태그의 className 으로 scss 속성을 부여하였더니 해결

클래스 생성 함수 수정

changeHandlerBgColor = () => {
  return this.state.btnChangeId && this.state.btnChangePw 
          ? "login-button trueColor" 
          : "login-button falseColor"
}

버튼 scss 수정 - nesting 기능 구현
클래스 이름 2개 일때 nesting 하는 법은 & 를 앞에 붙이는 것 같다

.login-button {
    width: 268px;
    height: 29.6px;
    margin: 8px 40px;
    /*background-color:rgba(0,149,246,.3);*/
    color:rgba(255,255,255,1);
    border-radius: 4px;
    border: 0px /*solid transparent*/;
    font-size: 14px;
    font-weight: 600;
    
    &.trueColor {
        background-color: #0562f7;
    }

    &.falseColor {
        background-color:rgba(0,149,246,.3);
    }
    
}

2. 메인의 로고 img 태그

Main.js 의 nav 의 로고 이미지가 Login.js의 로고 이미지 태그의 클래스 이름이 같아서 오류
클래스 이름을 바꿔주니 수정 완료

Main.js 수정한 것 / className을 수정 하였다 혹

.nav-img-logo {
    padding: 5px 10px 5px 0px;
}

.nav-text-logo {
    padding-left: 11.5px;
    border-left: 1.5px solid black;
}

Login.js

.img-logo {
    width: 175px;
    height: 51px;
    margin: 22px auto 30px;
}

0개의 댓글