iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Modern Web

用React刻自己的投資Dashboard系列 第 17

用React刻自己的投資Dashboard Day17 - Dashboard 2.0版路由功能

tags: 2021鐵人賽 React

如Day15的wireframe,為了要加上更多的功能,因此要在頂端列新增幾個按鈕,每個按鈕代表不同的路由,而不同的路由會導引到不同的頁面。本篇就先做到點擊頂端列按鈕可以跳轉頁面吧!

安裝react-router-dom

首先打開terminal並切換至專案資料夾,並執行下面這行,就會安裝好套件了。

npm install react-router-dom

Navbar製作新按鈕

這邊還是使用react-bootstrap的Nav元件來製作連結按鈕,也就是下面程式碼的Nav.Link,目前先規劃首頁與總體經濟兩個頁面,先作到兩個路由可以切換為主。

src\components\Navbar\Navbar.js

import React from 'react';
import styles from './Navbar.module.css';
import Navbar from 'react-bootstrap/Navbar';
import svgIcon from './navbaricon.svg';
import Nav from 'react-bootstrap/Nav';

const Topbar = () => {
  return (
    <Navbar className={styles.navbar}>
      <Navbar.Brand className={styles.title} href="/">
        <img
          alt=""
          src={svgIcon}
          width="30"
          height="30"
          className="d-inline-block align-top"
        />{' '}Invsetment Dashboard
      </Navbar.Brand>
      <Navbar.Collapse id="responsive-navbar-nav">
        <Nav className="me-auto">
          <Nav.Link href="/">首頁</Nav.Link>
          <Nav.Link href="/macroeconomics">總體經濟</Nav.Link>
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  );
};

export default Topbar;

做好後的畫面長這樣,上面有兩個按鈕,分別是首頁及總體經濟。

製作頁面元件

目前有兩個頁面分別是Home與Macroeconomics,先將這兩個分頁加到components資料夾內,首先在components內新增兩個資料夾:

其中Home資料夾內建立index.js檔,先簡單放個文字進去就好:

src\components\Home\index.js

import React from 'react';

const Home = () => {
  return (
    <React.Fragment>
      <h1>Home</h1>
    </React.Fragment>
  );
};

export default Home;

一開始實作的總體經濟的頁面,要從App.js內獨立出來,放在Macroeconomics資料夾內,App.js只留下控制路由的功能。

src\components\Macroeconomics\index.js

import React, { useState } from 'react';
import Charts from "../Charts/Charts";
import Selector from '../Selector/Selector';
import charts from '../../data/chart-collections.json';
import releases from '../../data/releases.json';
import sources from '../../data/sources.json';

const Macroeconomics = () => {
  const [filteredReleaseId, setFilteredReleaseId] = useState(0);
  const [filteredSourceId, setFilteredSourceId] = useState(0);

  const filteredCharts = charts.filter(chart => {
    let filterd = false
    if (filteredReleaseId === 0 && filteredSourceId === 0) { filterd = true }
    if (filteredReleaseId === 0 && filteredSourceId !== 0) {
      filterd = chart.source_id === filteredSourceId
    }
    if (filteredReleaseId !== 0 && filteredSourceId === 0) {
      filterd = chart.release_id === filteredReleaseId
    }
    if (filteredReleaseId !== 0 && filteredSourceId !== 0) {
      filterd = chart.release_id === filteredReleaseId && chart.source_id === filteredSourceId
    }
    return filterd
  });

  const releaseIdChangeHandler = (selectedReleaseId) => {
    setFilteredReleaseId(selectedReleaseId);
  };

  const sourceIdChangeHandler = (selectedSourceId) => {
    setFilteredSourceId(selectedSourceId);
  };

  return (
    <React.Fragment>
      <Selector
        selectedReleaseId={filteredReleaseId}
        selectedSourceId={filteredSourceId}
        releases={releases}
        sources={sources}
        onReleaseIdChange={releaseIdChangeHandler}
        onSourceIdChange={sourceIdChangeHandler}
      />
      <Charts charts={filteredCharts} />
    </React.Fragment>
  );
};

export default Macroeconomics;

新增路由控制元件

  • 路由資料:詳細說明每一個路由對應的路徑及元件...等資料。
    src\App-route.js

    import Home from "./components/Home/index";
    import Macroeconomics from "./components/Macroeconomics/index";
    
    //
    const routes = [
      {
        key: "route-home",
        name: "home",
        path: "/",
        withHeader: true,
        withFooter: true,
        public: true, // 若在維護開發中請設定 false
        authority: null,
        component: Home,
      },
      {
        key: "route-macroeconomics",
        name: "macroeconomics",
        path: "/macroeconomics",
        withHeader: true,
        withFooter: true,
        public: true, // 若在維護開發中請設定 false
        authority: null,
        component: Macroeconomics,
      }
    ];
    
    export default routes;
    
  • 路由層:將路由資料引入,並使用react-router-dom提供的元件撰寫路由層

    src\routerLayer\index.js

    import React from "react";
    import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
    import routes from "../App-route";
    import Layout from "../layout";
    
    const RouterLayer = () => {
      return (
        <Router>
          <Switch>
            {routes &&
              routes
                .filter((r) => r.public)
                .map((route) => (
                  <Route exact key={route.key} path={route.path}>
                    <Layout {...route} />
                  </Route>
                ))}
          </Switch>
        </Router>
      );
    };
    
    export default RouterLayer;
    
  • Layout:將頁面的基礎設定統一處理,例如header/body/footer的設定

    src\layout\index.js

    import React from "react";
    import Header from "./header";
    import Body from "./body";
    
    const Layout = (props) => {
      return (
        <React.Fragment>
          <Header />
          <Body {...props} />
        </React.Fragment>
      );
    };
    
    export default Layout;
    

    Layout的header設定,網頁的最上方是Navbar,因此直接拿來當header即可
    src\layout\header\index.js

    import React from "react";
    import Navbar from "../../components/Navbar/Navbar";
    
    const Header = () => {
      return <Navbar />
    }
    
    export default Header;
    

    Layout的body設定,這邊先不對body做設定,直接導入component
    src\layout\body\index.js

    import React from "react";
    
    const Body = ({ component: Component }) => {
      return (
        <Component />
      );
    };
    
    export default Body;
    

    上面路由層的設定比較複雜一些,主要是因為想讓程式可擴充性及可管理性高一些,例如只要調整header及body的index.js檔案,就可以適用在各個路由的頁面。

App.js引入路由層

上面的路由層寫好之後,就可以導入App.js了,如下程式碼,把整個路由架構寫在路由層內之後,App.js就會變得非常簡潔。

src\App.js

import React from 'react';
import './App.css';
import RouterLayer from "./routerLayer";

function App() {
  return (
    <div className="App">
      <RouterLayer />
    </div>
  );
}

export default App;

小結

本篇路由層參考其他專案架構,寫出一個比較可以維護的資料夾結構,也很感謝工程師朋友願意分享專案架構給我參考,跟React提供的basic版路由架構差蠻多的,學習到很多。下一篇就來製作首頁的wireframe吧。


上一篇
用React刻自己的投資Dashboard Day16 - react-router-dom讓SPA也有路由
下一篇
用React刻自己的投資Dashboard Day18 - 選單列active style功能
系列文
用React刻自己的投資Dashboard30

尚未有邦友留言

立即登入留言