{ The Rithm Blog. }

Intro To Modern React - Preview February 05, 2020

Over the next 6 weeks, Rithm School is offering a new format of full-day coding workshops, available both in-person and remotely. In this blog post, workshop instructor Michael Hueter will give a sneak preview of a topic covered the upcoming Intro to Modern React workshop.

Introducing Bootstrap to Our React Project

Foreword

This is a condensed snippet of example curriculum from an upcoming workshop.

This guide is assuming you have a basic "Create React App" project set up. If not, you can do this in 1 minute by doing the following steps in your terminal:

  1. npm install --global create-react-app
  2. create-react-app bootstrap-demo
  3. open the newly-created bootstrap-demo directory in your text editor
  4. run npm start to start the dev server.

Pure Bootstrap

Most developers are familiar with the CSS framework Bootstrap, one of the most popular frontend frameworks in the world ever since it was originally developed at twitter in 2010.

Developing with Bootstrap and plain HTML is pretty straightforward; you just add a few Bootstrap classes to regular HTML elements and they start to look and/or behave like components.

Let's take a look at some regular old HTML + Bootstrap:

<div class="row justify-content-center">
  <div class="col-3">
    <div class="card mt-5">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
        <p class="card-text">
          Some quick example text to build on the card title and make up the
          bulk of the card's content.
        </p>
      </div>
    </div>
  </div>
</div>

This is what it looks like in the browser:

A plain old bootstrap card centered in a row + column

Nothing fancy, just a card inside a col-3 inside a row. The row and col classes are used for bootstrap's famous grid system which is now based on flexbox.

React-Bootstrap

One way to apply this to React is to just copy all of that markup and change class to className. But that kind of defeats the purpose of React right? What about components?

Luckily, there is a recently-updated official Bootstrap library for React called React Bootstrap. This is separate from Reactstrap, which was formerly the recommended way to go for using Bootstrap with React until the new updates from the official package. The updates included support for Bootstrap 4 as well as some some awesome modernizations like all of their example docs using hooks! Also, out-of-the-box typings for TypeScript 💙.

To install React Bootstrap (the quick way), we can just:

npm install react-bootstrap bootstrap

and then go into public/html and add the bootstrap CDN link at the top of the file:

<link
   rel="stylesheet"
   href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
   integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
   crossorigin="anonymous"
 />

Once you have this, we can change our chain of div elements into React-bootstrap components!

import React from "react";
import { Card, Row, Col } from "react-bootstrap";

function App() {
  return (
    <Row className="justify-content-center">
      <Col xs="3">
        <Card className="mt-5">
          <Card.Body>
            <Card.Title>Card title</Card.Title>
            <Card.Subtitle>Card subtitle</Card.Subtitle>
            <Card.Text>
              Some quick example text to build on the card title and make up the
              bulk of the card's content.
            </Card.Text>
          </Card.Body>
        </Card>
      </Col>
    </Row>
  );
}

export default App;

Above you can see we have a much more React-y way of doing things. We've removed all of the component classes, and all that's left are the utility classes like the centering (justify-content-center) the margin top (mt-5).

Getting More Advanced

If you've had any Bootstrap and/or React experience previously, you may have found the above example to be quite simple. So let's do something more interesting! What if we wanted to get creative and make your page show different content based on whichever card the user selects? What we want is something like a Bootstrap Nav component, but using cards instead of tabs... (This is actually something I've done on the job in real life 🙂)

Here's what we want to build:

Switching between potato and tomato cards as navs

If you check out React-Bootstrap's documentation on Navs, it says (emphasis mine):

<Nav> markup is very flexible and styling is controlled via classes so you can use whatever elements you like to build your navs. By default <Nav> and <Nav.Item> both render <div>s instead of <ul> and <li> elements respectively.

So this is looking like it's possible!

Using Hooks for Nav State

First things first, let's set up a hook to keep track of state:

import React, { useState } from "react";

function App() {
  // keep track of whether potatoes or tomatoes is selected
  const [activeItem, setActiveItem] = useState("potatoes");
 
  /*...more stuff...*/
}

For reference, I basing our code off of this example of controlled tabs in React Bootstrap.

The activeItem value from state will refer to either "potatoes" or "tomatoes", which are going to be assigned to the activeKey prop on our nav component.

The setActiveItem state updater function will be passed to the onSelect props on our nav component.

We will also set the eventKey props of our nav links to be the value we want to associate with them in state.

So, using the standard Nav components we'll have something like this:

import React, { useState } from "react";
import { Card, Row, Col, Nav, Container } from "react-bootstrap";

function App() {
  const [activeItem, setActiveItem] = useState("potatoes");

  return (
    <Container>
      <Row className="justify-content-center">
        <Col>
          <h1 className="text-center">You've selected {activeItem}</h1>
        </Col>
      </Row>
      <Nav
        className="justify-content-center"
        activeKey={activeItem}
        onSelect={setActiveItem}
      >
        <Col xs="3">
          <Nav.Link eventKey="potatoes">Potatoes</Nav.Link>
        </Col>
        <Col xs="3">
          <Nav.Link eventKey="tomatoes">Tomatoes</Nav.Link>
        </Col>
      </Nav>
    </Container>
  );
}

This looks like this:

Nav links without cards

Almost there! 👏 We have the main functionality we want, but it doesn't look good yet.

Getting Super Fancy

Throughout the React Bootstrap docs examples and API, there is a special, super powerful prop hiding in plain sight called as. Virtually every component has it as a prop -- and it is an interesting prop because it takes another component as its value. And what magically happens is that you maintain the functionality of the original component, but can take on the look of any other component.

So for us, we will use as in two places. First of all, we'll make our Nav component appear as a Row:

<Nav
  as={Row}
  className="justify-content-center"
  activeKey={activeItem}
  onSelect={setActiveItem}
>
  {/* other stuff */}
</Nav>

Secondly, we'll make our Nav.Link components appear as Card components, and give them regular <Card> child components:

<Nav.Link as={Card} eventKey="potatoes">
  <Card.Body>
    <Card.Title>Potatoes</Card.Title>
    <Card.Text>🥔🥔🥔🥔🥔</Card.Text>
  </Card.Body>
</Nav.Link>

Switching between potato and tomato cards as navs

Yes! 🎉 That did it, we now have cards where we once had links.

The final code looks like this:

import React, { useState } from "react";
import { Card, Row, Col, Nav, Container } from "react-bootstrap";
import "./App.css";

function App() {
  const [activeItem, setActiveItem] = useState("potatoes");

  return (
    <Container>
      <Row className="justify-content-center">
        <Col>
          <h1 className="text-center">You've selected {activeItem}</h1>
        </Col>
      </Row>
      <Nav
        as={Row}
        className="justify-content-center"
        activeKey={activeItem}
        onSelect={setActiveItem}
      >
        <Col xs="3">
          <Nav.Link as={Card} eventKey="potatoes">
            <Card.Body>
              <Card.Title>Potatoes</Card.Title>
              <Card.Text>🥔🥔🥔🥔🥔</Card.Text>
            </Card.Body>
          </Nav.Link>
        </Col>
        <Col xs="3">
          <Nav.Link as={Card} eventKey="tomatoes">
            <Card.Body>
              <Card.Title>Tomatoes</Card.Title>
              <Card.Text>🍅🍅🍅🍅🍅</Card.Text>
            </Card.Body>
          </Nav.Link>
        </Col>
      </Nav>
    </Container>
  );
}

export default App;

Bonus: Active Card Styles

If you notice at the top of the file, I'm importing App.css. This is how I got the background color when the Nav.Link aka Card is the activeItem:

.card.active {
  background-color: tomato;
}

.card:hover {
  cursor: pointer;
}

Btw check out that background color! 😁

Note that this actually provides some insight into how React Bootstrap works. That activeKey prop we set on the original Nav component will actually apply the active Bootstrap CSS class to the selected child component.

More at the Workshop

This has been a sneak preview of some of the things we'll do at the workshop. I hope you got to learn something just now! If you are feeling a little overwhelmed, don't worry, the Intro to Modern React workshop will build up to this over the course of the day and will explain in much greater detail things like props, state, and hooks. We'll also do more sophisticated things and use React Bootstrap components as part of a larger app.

If, on the other hand, you're feeling like that was a cakewalk and want even more advanced React content, consider joining me for React Hooks In-Depth or React, TypeScript, and GraphQL!

Until next time! 👋

Written by Michael

Back to all posts

Get Started with Rithm School