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:
npm install --global create-react-app
create-react-app bootstrap-demo
- open the newly-created
bootstrap-demo
directory in your text editor - 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:
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:
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:
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>
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!