[smartics : routing]

This weekend I worked on showing historic data. To actually show anything but the current overview I had to get the menu in the application working first. For that I am using another library called react-router. I will quickly show how to include it in a react app that is already using bootstrap.

First we need the usual npm install to get the following two dependencies: react-router-dom for handling the routing, and react-router-bootstrap for being easily able to include it in the bootstrap parts of the code. This currently extends the package.json with:

"repository": {
    "react-router-bootstrap": "^0.25.0",
    "react-router-dom": "^5.1.2",

With that the menu in index.jsx can be enhanced with links and routes handling the wanted output. At first containers for the links in the menu and the actual router and route tags are imported from the react-router library.

import { IndexLinkContainer, LinkContainer } from 'react-router-bootstrap';
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

In the first part the menu brand icon and link gets an IndexLinkContainer around to link to the main path. The other Nav.Link elements also get their LinkContainer to route to a specific path. Here I use .jsx for easier distinction later on, but anything will do.

class Index extends Component {
   render() {
      return (
         <Router>
         <Container fluid>
            <Row>
               <Col>
                  <Navbar bg="light" expand="md" fixed="top" collapseOnSelect>
                     <IndexLinkContainer to="/">
                        <Navbar.Brand>
                           <img src="images/logo.png" width="26" height="30" className="d-inline-block align-top" alt="logo" />
                           {' '}smartics
                        </Navbar.Brand>
                     </IndexLinkContainer>
                     <Navbar.Toggle aria-controls="basic-navbar-nav" />
                     <Navbar.Collapse id="basic-navbar-nav">
                        <Nav className="mr-auto">
                           <LinkContainer to="/history.jsx">
                              <Nav.Link>history</Nav.Link>
                           </LinkContainer>
                           <LinkContainer to="/settings.jsx">
                              <Nav.Link disabled>settings</Nav.Link>
                           </LinkContainer>
                           <LinkContainer to="/about.jsx">
                              <Nav.Link>about</Nav.Link>
                           </LinkContainer>
                        </Nav>
                     </Navbar.Collapse>
                  </Navbar>
               </Col>
            </Row>

The second part is to implement the logic for the different routes. I use a Switch from react-router to do it directly in there, but there are other possibilities. The original charger and inverter data gets the main path (line 49) whereas the new history component gets the path like specified in the LinkContainer above. The exact parameter is to only match exactly that path. This is especially needed for the index, as that would also match the other routes.

            <Row>
               <Switch>
                  <Route exact path="/">
                     <Col lg={4}>
                        <ChargerApp />
                     </Col>
                     <Col lg={8}>
                        <InverterApp />
                     </Col>
                  </Route>
                  <Route exact path="/history.jsx">
                     <Col lg={12}>
                        <InverterHistory />
                     </Col>
                  </Route>
                  <Route exact path="/about.jsx">
                     <div className='boxed'>Application info.</div>
                  </Route>
               </Switch>
            </Row>
         </Container>
         </Router>
      );
   }
}

That is basically all to include react-router. Though one thing should not be missed: if it is an app that does the routing also on some other level, like a springboot app, then the main Controller has to be adapted to also forward other paths to the main index page. This is the relevant part of the HomeController.java to prevent a 404 on the reload of a specific page or a bookmarked link. Here the earlier mentioned .jsx path ending comes in handy.

@Controller
public class HomeController {

   @GetMapping(value = "/*.jsx")
   public String page() {
      return "static/index";
   }
}

Next I’ll show a bit of historic data. I have already gathered a few weeks and could even compare January and February soon. I might try out some actions and additional visualizations in d3 too.

— Raphael

resources

Leave a comment