React & Django 프로젝트

input태그를 이용하여 직관적으로 한줄 노트를 작성할수 있는 앱

R&D Header (nav바 디자인하기)

page routing

Project : frontend

    src/
    ├──    styles/ 
    |       ├── utils.scss
    |       └── index.scss
    ├── containers/ # 리액트 컨테이너 파일들 집합
    ├── components/ # 리액트 컴포넌트 파일들 집합
    |       ├── /structure
    |       ├── /Header
    |       |        ├── Header.js   # header 관련 코드 파일
    |       |        ├── Header.scss # header 관련 scss 파일
    |       |       |       └── index.js    # header export   ->  structure.js
    |       |       ├── MainStructure.js    # 조각 모음
    |       |       ├── MainStructure.scss  # scss 조각모음
    |       |       └── index.js            # structure export ->  main.js
    |       └── App.js  -> Root.js -> index.js
    ├── pages/ -> APP.js 
    |       ├── Auth.js     # login/register page
    |       ├── Main.js     # Main page  
    |       ├── Notfound.js # 지정되지 않은 page
    |       └── index.js
    └── store/     # redux모듈들과 configure파일들 집합
            ├── module/
            |      ├── index.js
            |      └── ping.js
            └── configure.js
1
2
# 라우팅
$ npm install react-router-dom

Root.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from "react";
import App from "./components/App";
import { Provider } from "react-redux";
import store from "./store/configure";
import { BrowserRouter } from "react-router-dom";

const Root = () => {
return (
<Provider store={store}>
// 감싸준다
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
};

export default Root;

pages/Main.js : 노트들이 리스트되어 나타날 페이지

1
2
3
4
5
6
7
8
import React from "react";

const Main = () => {
return <div>Main Page</div>;
};

export default Main;

pages/Auth.js : 로그인 / 회원가입 페이지

1
2
3
4
5
6
7
8
import React from "react";

const Auth = () => {
return <div>Auth Page</div>;
};

export default Auth;

pages/NotFound.js : 라우팅 되지 않은 곳에서 나타날 페이지

1
2
3
4
5
6
7
8
import React from "react";

const NotFound = () => {
return <div>NotFound Page</div>;
};

export default NotFound;

pages/index.js : 페이지들을 한곳에 모아줌

1
2
3
4
export { default as Main } from "./Main";
export { default as Auth } from "./Auth";
export { default as NotFound } from "./NotFound";

components/App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from "react";
import { Switch, Route } from "react-router-dom";
import { Main, Auth, NotFound } from "../pages";

class App extends Component {
render() {
return (
<div>
<Switch>
<Route path="/" exact={true} component={Main} />
<Route path="/auth/:kind" exact={true} component={Auth} />
<Route component={NotFound} />
</Switch>
</div>
);
}
}

export default App;

결과

Header 만들기

1
2
3
4
5
$ npm install react-icons open-color include-media classnames
# react-icons : 로그아웃 버튼
# open-color : color제공 라이브러리
# include-media : 미디어 쿼리를 좀더 자유롭게 사용하게 해줌
# classnames : 여러개의 클래스를 한번에 사용하게도 하고, scss와 bind하여 굳이 styles라는 이름을 사용하지 않아도 되게하는 라이브러리

기본 동작 구조

components(header) -> MainStructure -> page -> App -> Root -> index

main scss 설정(styles/utils.scss)

1
2
3
4
5
6
7
8
9
@import "~open-color/open-color";
@import "~include-media/dist/include-media";

$breakpoints: (
small: 320px,
medium: 768px,
large: 1024px,
wide: 1400px
);

header 설정

/components/structure/Header/Header.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from "react";
import styles from "./Header.scss";
import classNames from "classnames/bind";
import { Link } from "react-router-dom";
import { MdLock } from "react-icons/md";

const cx = classNames.bind(styles);

const Header = ({ onLogout }) => (
<div className={cx("header")}>
<Link to={"/"} className={cx("logo")}>
D-Note
</Link>
<div className={cx("logout")}>
<MdLock onClick={onLogout} />
</div>
</div>
);

export default Header;

/components/structure/Header/Header.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@import "../../../styles/utils.scss";

.header {
background: $oc-violet-6;
height: 5rem;

display: flex;
align-items: center;

.logo {
color: white;

font-weight: 800;
font-size: 1.5rem;

cursor: pointer;

margin-left: 1rem;

user-select: none;
}

.logout {
margin-left: auto;
margin-right: 1rem;
color: white;

font-weight: 800;
font-size: 2rem;

cursor: pointer;
}
}

index.js

1
2
// export
export { default } from './Header';

MainStructure.js : 여러개의 components를 모아주는 곳

components/structure/MainStructure.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from "react";
// import styles from "./MainStructure.scss";
import classNames from "classnames/bind";
import Header from "./Header";

// const cx = classNames.bind(styles);

const MainStructure = ({ children }) => (
<div>
<Header />
<main>{children}</main>
</div>
);

export default MainStructure;

components/structure/index.js

1
export { default } from './MainStructure';

pages/Main.js

1
2
3
4
5
6
7
8
import React from "react";
import MainStructure from "../components/structure/MainStructure";

const Main = () => {
return <MainStructure>Main Page</MainStructure>;
};

export default Main;

결과