Skip to content

Latest commit

 

History

History
342 lines (253 loc) · 9.71 KB

10-setup-react-router.md

File metadata and controls

342 lines (253 loc) · 9.71 KB

สร้างระบบ Navigation ด้วย React Router

รูปแบบของ React-Redux App ก่อนและหลังใช้งาน Router

ก่อนใช้ Router

Paper React   React Native 33

หลังใช้ Router

Paper React   React Native 34

1. ติดตั้ง Module

npm i react-router-dom connected-react-router redux-logger

2. สร้าง Root Reducer เพื่อใช้งาน Reducer อื่นๆ ของเรา ร่วมกับ Reducer ของ React-Router

สร้างไฟล์ src/redux/root.reducer.js

ไฟล์นี้จะเป็นตัวรวม reducer ในแอพของเรา และสามารถสร้างเพิ่มได้

แน่นอนว่าตอนนี้เรามีแค่ homepageReducer และเราจะเพิ่ม reducer ของ react-router ที่ชื่อ connectRouter() เข้ามา

สังเกตว่าเราตั้งชื่อให้กับ reducer แต่ละตัวได้ด้วย

import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'
import homepageReducer from "./homepage.reducer";

export default (history) => combineReducers({
  router: connectRouter(history),
  homepage: homepageReducer
}) 

3. ปรับให้ Store ทำงานกับ History Module และ React-router-middleware

เปิดไฟล์ src/redux/store.js

เร่ิมแรกเราจะเอา History Module เข้ามาใช้

import { createBrowserHistory } from 'history'

export const history = createBrowserHistory()

จากนั้น เราจะเอา rootReducer มาใช้แทน homepageReducer

import createRootReducer from "./root.reducer";

export default function configureStore() {
    const store = createStore(
        createRootReducer(history),
        applyMiddleware(logger),
       ),
    );
    return store;
}

สังเกตว่าเราเริ่มมีการเอา middleware มาใช้กับ Redux Store ผ่าน applyMiddleware()

โดยตัวแรกที่เอามาใช้ก็คือ redux-logger

และเราจะใช้ compose จาก redux เป็นตัวประกอบ middleware เดิม และ middleware ของ react-routerเข้าไปใน store

import { createStore, applyMiddleware, compose } from 'redux';   
import { routerMiddleware } from 'connected-react-router'

const store = createStore(
    createRootReducer(history),
    compose(
        applyMiddleware(
            routerMiddleware(history),
            logger
        ),
    ),
);

ไฟล์เต็ม Store.js

import { createStore, applyMiddleware, compose } from 'redux';   
import { logger } from 'redux-logger';
import { routerMiddleware } from 'connected-react-router'
import { createBrowserHistory } from 'history'
import createRootReducer from "./root.reducer";

export const history = createBrowserHistory()

export default function configureStore() {
    const store = createStore(
        createRootReducer(history),
        compose(
            applyMiddleware(
              routerMiddleware(history)
              logger
            ),
          ),
    );
    return store;
}

4. ลบ <Provider> ออกจาก App.js

ไฟล์เต็ม src/App.js

import React from 'react';
import './App.css';
import MenuBar from './components/MenuBar';
import { Layout } from 'antd';
import HomePage from './pages/home-page/HomePage';
const { Footer } = Layout;

function App() {
  return (
      <div>
        <Layout className="layout">
          <MenuBar />
          <HomePage />
          <Footer style={{
            textAlign: 'center'
          }}>React Redux Workshop ©2012-2019 Created by Nextflow.in.th</Footer>
        </Layout>,
      </div>
  );
}

export default App;

5. นำ history มากำหนดให้กับ Connected Router ในระดับนอกสุดของ Component

เปิดไฟล์​ src\index.js

เริ่มจาก import ส่วนที่ต้องการเข้ามาใช้งาน

import configureStore, { history } from "./redux/store";
import { ConnectedRouter } from 'connected-react-router'

และครอบ App ของเราด้วย <ConnectedRouter>

ReactDOM.render((
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App/>
    </ConnectedRouter>
  </Provider>
), document.getElementById('root'));

ไฟล์เต็ม index.js

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

import {Provider} from 'react-redux'
import configureStore, { history } from "./redux/store";
import { ConnectedRouter } from 'connected-react-router'

const store = configureStore();

ReactDOM.render((
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App/>
    </ConnectedRouter>
  </Provider>
), 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();

6. เรียกใช้ และ ของ react-router-dom

เปิดไฟล์ src/App.js

เราจะมีการ import Component ที่ต้องใช้มาจาก react-router-dom

import { Route, Switch } from "react-router-dom";

และ HomePage component

import HomePage from './pages/home-page/HomePage';

ทำให้เราสามารถวางระบบ Route เพื่อจัดการแสดงหน้าตาของแอพได้

<Switch>
    <Route path="/" exact component={Dashboard} />
</Switch>

ไฟล์เต็ม src/App.js

import React from 'react';
import './App.css';
import MenuBar from './components/MenuBar';
import { Layout } from 'antd';
import HomePage from './pages/home-page/HomePage';
import { Route, Switch } from "react-router-dom";
const { Footer } = Layout;

function App() {
  return (
      <div>
        <Layout className="layout">
          <MenuBar />
          <Switch>
            <Route path="/" exact component={HomePage} />
          </Switch>
          <Footer style={{
            textAlign: 'center'
          }}>React Redux Workshop ©2012-2019 Created by Nextflow.in.th</Footer>
        </Layout>,
      </div>
  );
}

export default App;

7. ปรับให้ mapStateToProps ของ Component ต่างๆ รับกับ Ruducer แบบรวม

จะเห็นว่าหลังจากเราใช้ combineReducer แล้วตัว Component ของเราจะพังในส่วน mapStateToProps เป็นแถบๆ

เพราะในที่นี้ state object ที่ส่งมาเข้า mapStateToProps จะได้เป็นโครงสร้างใหม่ ตามที่เราตั้งชื่อไว้ในไฟล์ root.reducer.js

ให้เราเริ่มเช็ค state ที่ส่งเข้ามาใน mapStateToProps ของ Component ที่มีการใช้งาน และปรับให้เป็นแบบใหม่

ไฟล์ src/pages/home-page/NoteList.js

const mapStateToProps = (state) => {
    console.log(state);
    return {
        noteData: state.homepage.notes
    }
}

8. สร้าง Login Page และเอามาแสดงใน App.js

สร้างไฟล์ src/pages/login-page/LoginPage.js

// ใช้ snippet rcredux ได้
import React, { Component } from 'react'
import { connect } from 'react-redux'

class LoginPage extends Component {
    render() {
        return (
            <div>
                Log me in
            </div>
        )
    }
}

const mapStateToProps = (state) => ({
    
})

const mapDispatchToProps = {
    
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginPage)

เสร็จแล้วให้เอา LoginPage component มาใช้กับ <Switch> ใน App.js Component

import LoginPage from './pages/login-page/LoginPage';

ไฟล์เต็ม src/App.js

import React from 'react';
import './App.css';
import MenuBar from './components/MenuBar';
import { Layout } from 'antd';
import HomePage from './pages/home-page/HomePage';
import { Route, Switch } from "react-router-dom";
import LoginPage from './pages/login-page/LoginPage';
const { Footer } = Layout;

function App() {
  return (
      <div>
        <Layout className="layout">
          <MenuBar />
          <Switch>
            <Route path="/" exact component={LoginPage} />
            <Route path="/home" exact component={HomePage} />
          </Switch>
          <Footer style={{
            textAlign: 'center'
          }}>React Redux Workshop ©2012-2019 Created by Nextflow.in.th</Footer>
        </Layout>,
      </div>
  );
}

export default App;