서브 라우트는 라우트 내부에 라우트를 다시 정의 하는 것을 의미한다. 사용하는 경우에는 App에서 라우팅을 여러군대로 한다면 코드는 App에서 정말 복잡한 결과를 낼것이다. 우리는 여러개의 컴포넌트를 만들고 연관되는 컴포넌트끼리 내부에서 다시 라우터를 정의해 App에서의 다양하고 복잡한 routing을 효과적으로 정리가 가능하다.

예를들어서 Location에 관련된 컴포넌트에서 Location은 Seoul, Gyonggi-do, (...) 가 있을때 App에 모든 도시의 리스트를 정의하기에는 복잡하다. Location Routing Example 에서 App에 seoul, gyonngi-do를 정의 했는데 Locations라는 라우트 컴포넌트를 따로 정의하고, Location 컴포넌트를 서브 라우트로 사용해보자

코드

import React from 'react';
import { Route, Link } from 'react-router-dom';
import './App.css';

import Home from './components/Home';
import Search from './components/Search';
import Locations from './components/Locations';

const App = () => {
  return (
    <div>
      <Link to="/">홈</Link>
      <Link to="/search">검색</Link>
      <Link to="/locations">위치</Link>

      <Route path="/" component={Home} exact={true}></Route>
      <Route path="/search" component={Search}></Route>
      <Route path="/locations" component={Locations}></Route>
    </div>
  );
};

export default App;
import React from 'react';
import { Link, Route } from 'react-router-dom';
import Location from './Location';

const Locations = () => {
  return (
    <div>
      <h1> 도시 목록 </h1>
      <ul>
        <li>
          <Link to="/locations/seoul">서울</Link>
        </li>
        <li>
          <Link to="/locations/gyonggi">경기</Link>
        </li>
      </ul>
      <Route
        path="/locations"
        exact={true}
        render={() => <div> 지역을 선택해 주세요. </div>}
      />
      <Route path="/locations/:cityname" component={Location} />
    </div>
  );
};

export default Locations;

Parameter, Query Example

  • /user/lee
  • /search?keyword="hi

위에서 user에 lee를 넘기는 방식이 parameter로 특정 사용자를 조회할때 사용하고, query는 키워드를 검색할때 페이지에 필요한 옵션을 전달할 때 사용을 하게 된다.

URL Parameter

  • match라는 객체안의 params 값을 참조
import React from 'react';

const data = {
  seoul: {
    name: '서울',
    location: 'seoul'
  },
  gyonggi: {
    name: '경기도',
    location: 'gyonngi-do'
  }
};

const Location = ({ match }) => {
  const { cityname } = match.params;
  const city = data[cityname];
  if (!city) {
    return (
      <div>
        <h1> {cityname} 은 존재하지 않는다.</h1>
      </div>
    );
  }

  return (
    <div>
      <h1>
        {' '}
        {cityname} ({city.name})
      </h1>
      <p>{city.location}</p>
    </div>
  );
};

export default Location;
  • App.js에서 routing을 정의
import React from 'react';
import { Route, Link } from 'react-router-dom';
import './App.css';

import Home from './components/Home';
import Search from './components/Search';
import Location from './components/Location';

const App = () => {
  return (
    <div>
      <Link to="/">홈</Link>
      <Link to="/search">검색</Link>
      <Link to="/location/seoul">서울</Link>
      <Link to="/location/gyonngi">경기</Link>
      <Link to="/location/star">별나라</Link>

      <Route path="/" component={Home} exact={true}></Route>
      <Route path="/search" component={Search}></Route>
      <Route path="/location/:cityname" component={Location}></Route>
    </div>
  );
};

export default App;

URL 쿼리

  • url 쿼리의 경우에는 match와 다르게 location의 객체에 있는 값을 조회가 가능하다.
  • /search?keyword=hi의 url을 호출했을때 location의 객체의 형태는 아래와 같다.
{
  "pathname": "/search",
  "search": "?keyword=hi"
}
  • query 문자열을 객체로 변환할때는 qs의 라이브러리를 사용한다
yarn add qs
import React from 'react';
import qs from 'qs';

const Search = ({ location }) => {
  // ?keyword=
  const query = qs.parse(location.search, {
    ignoreQueryPrefix: true // prefix: ?
  });

  const keyword = query.keyword;

  return (
    <div>
      <h1>Search</h1>
      <p> 검색 쿼리는 {keyword}</p>
    </div>
  );
};

export default Search;
  • 다음과 같이 추가한 이후에 url을 http://localhost:3000/search?keyword=hi을 통해 접속하면 원하는 결과를 얻을 수 있다.

Routing 이란?

routing 은 특정 주소에 특정 페이지를 보여주는게 라우팅(Routing)

react-router 사용하기

default로 react는 routing의 기능이 없기 때문에 라우팅 라이브러리를 사용해야 한다. 가장 많이 사용하는 routing library는 react-router

yarn add react-router-dom

프로젝트에 라우터를 적용

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

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

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

위 코드에서 아래와 같이 추가

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <BrowserRouter>
    <App />{' '}
  </BrowserRouter>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

두개의 컴포넌트 생성하기

import React from 'react';

const Search = () => {
  return (
    <div>
      <h1>Search</h1>
    </div>
  );
};
export default Search;

import React from 'react';

const Home = () => {
  return (
    <div>
      <h1>Home</h1>
    </div>
  );
}; 
export default Home;

App.js 를 수정

  • app에서 exact={true}를 사용하지 않으면 search로 검색했을때 Home, Search의 두개의 페이지가 화면에 중복으로 표시된다.
  • Link를 클릭하면 다른 주소로 이동시켜주는 컴포넌트
  • a tag 를 사용하면 화면이 새로고침 된다. (페이지를 렌더링)
  • Link 사용하면 페이지 새로고침 하지 않고
import React from 'react';
import { Route, Link } from 'react-router-dom';
import './App.css';

import Home from './components/Home';
import Search from './components/Search';

const App = () => {
  return (
    <div>
      <Link to="/">홈</Link>
      <Link to="/search">검색</Link>
      <Route path="/" component={Home} exact={true}></Route>
      <Route path="/search" component={Search}></Route>
    </div>
  );
};

export default App;

EsLint, Prettier는 VS Code에서 React를 개발할때 설치하면 좋은 확장 툴이다.
ESLint는 문법 검사, Prettier는 코드 스타일 자동 정리를 해주는 툴이다.

여러 개발자들이 동시에 개발하는 프로젝트라면 Prettier는 무조건 필수라고 할 수 있다.
git에서 merge할때 indentation 관련한 코멘트를 받으면 ... 창피

ESLint는 설치하고 바로 사용하면 되고, Prettier의 경우에는 프로젝트에 설정을 해야 한다.
프로젝트의 root directory에서 .prettierrc라는 파일을 설정하고
아래와 같이 프로젝트에서 사용할 prettierrc를 정의를 하면된다.

prettierrc example

{
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "singleQuote": true,
  "bracketSpacing": true,
  "jsxBracketSameLine": true
}

prettier에 관련한 옵션은 다음 사이트에서 확인

코드 자동으로 정렬

VS Code에서는 코드를 저장할때 자동으로 정렬을 해준다.

[Code] - [Preference] - [Settings] 
에서 format on save 을 검색하고 체크

Homebrew 설치

 /usr/bin/ruby -e "$(curl -fsSl https://raw.githubusercontent.com/Homebrew/install/master/install)"

nvm 설치

  • node.js 버전 관리 툴
  • node.js의 버전 업데이트를 하거나 프로젝트 별로 버전이 다른 node.js를 사용하기 위해서
sudo curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash
  • 환경설정
# ~/.bsah_profile 에 아래와 같이 추가 (macos 기준)

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" 

node 설치

  • nvm이 설치되었다는 가정하에서아래와 같이 최신 버전으로 설치
nvm install --lts

yarn 설치

brew update
brew install yarn
yarn config set prefix ~/.yarn
echo 'export PATH="$(yarn global bin):$PATH"' >> ~/.bash_profile

Visual Studio Code로 React를 개발하면서 유용한 확장 프로그램을 정리

ESLint

  • 문법 및 코드 스타일을 검사

reactjs Code Snippets

  • 라이프사이클 함수를 작성할때 단축 단어를 사용해 코드 자동 생성

Prettier-Code formatter

  • 내가 설정한 코드 포맷의 스타을로 자동 정리해주는 도구

react import package absolute path 하는 방법

Can't resolve module 이라는 에러가 난다면 상대경로가 아닌 절대경로로 하는게 좋다. 상대 경로로 할 경우에는 import module from '../../../과 같이 명시를 해줘야 하니... 절대 경로로 하는 방법은 아래와 같다.

Project의 ROOT (README.md를 보통 만드는)에 가서 .env의 파일을 만들고 NODE_PATH=src/ 다음과 같이 입력하면 src의 아래에 있는 pages, modules 등을 import Module from 'modules/modulename' 으로 입력하면 된다.

만약 적용이 안된다면 재시작을 해주면 정상적으로 반영된다.

react앱에서 데이터는 위에서 아래로 props을 통해 전달되지만 여러 컴포넌트들에 전해줘야 하는 props의 경우에는 context를 이용하면 트리 단계마다 명시적으로 props을 넘겨주지 않아도 많은 컴포넌트가 값을 공유할 수 있다.

global 변수로서 context를 사용하는 경우는 로그인한 유저, 테마, 선호하는 언어 등이 있을 수 있다. 코드는 아래와 같다.

class App extends React.Component {
  render() {
    return <Toolbar theme="dark" />;
  }
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton theme={props.theme} />
    </div>
  );
}

class ThemedButton extends React.Component {
  render() {
    return <Button theme={this.props.theme} />;
  }
}

위와 같이 props으로 넘기는게 아니라 아래와 같이 context를 사용하면 자식에 props을 넘길 필요가 없음

const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() { 
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component { 
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

context를 사용하면 컴포넌트를 재사용하기가 어려워지므로 꼭 필요할때만 사용해야 한다.

+ Recent posts