DEV Community

loading...
Cover image for Using Bootstrap 5 with React
Codeply

Using Bootstrap 5 with React

Carol Skelly
Top girl dev on StackOverflow. Creator of Codeply.com. Love frontend, but full-stack too! #vue #vuetify #bootstrap #css #javascript #react #net
Updated on ・2 min read

How to use the new Bootstrap 5 with React

Bootstrap and React have both been around for a while now, but now that the Bootstrap 5 beta is out, there's finally something to cheer about! 🙌

Now that Bootstrap 5 no longer requires jQuery, using it in your React app is much easier and without conflicts! 😲 Now that Bootstrap 5 components are written as vanilla JS plugins, you get improved alignment with React's best patterns & practices.

This also means it's possible to use Bootstrap 5 components without the need for a 3rd party library like react-bootstrap or reactstrap.


First up, add Bootstrap to your React app's package.json:

npm install bootstrap --save

Once Bootstrap is included, you'll be able to import components the way you do with any JS module. For example, let's import Bootstrap's Toast component...

import { Toast} from bootstrap

And then use it with React's useEffect and useState hooks...

function ToastDemo() {
    var [toast, setToast] = useState(false);
    const toastRef = useRef();

    useEffect(() => {
        var myToast = toastRef.current
        var bsToast = bootstrap.Toast.getInstance(myToast)

        if (!bsToast) {
            // initialize Toast
            bsToast = new Toast(myToast, {autohide: false})
            // hide after init
            bsToast.hide()
            setToast(false)
        }
        else{
            // toggle
            toast ? bsToast.show() : bsToast.hide()

        }
    })

    return (
    <div className="py-2">
        <button className="btn btn-success" onClick={() => setToast(toast => !toast)}>
            Toast {toast?'hide':'show'}
        </button>
        <div className="toast" role="alert" ref={toastRef}>
            <div className="toast-header">
                <strong className="me-auto">Bootstrap 5</strong>
                <small>4 mins ago</small>
                <button type="button" className="btn-close" onClick={() => setToast(false)} aria-label="Close"></button>
            </div>
            <div className="toast-body">
              Hello, world! This is a toast message.
            </div>
        </div>
    </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Or, (if that wasn't easy enough) use the new namespaced data-bs- attributes directly in your markup. For example, let's use the Bootstrap 5 Collapse component...

function CollapseDemo() {
  return (
    <div className="py-2">
        <button className="btn btn-primary" data-bs-target="#collapseTarget" data-bs-toggle="collapse">
            Toggle collapse
        </button>
        <div className="collapse" id="collapseTarget">
            This is the toggle-able content!
        </div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now you can easily use any of the Bootstrap 5 Components in your React project. Check out these Bootstrap 5 React examples that use the Bootstrap 5 Toast, Alert, Collapse, Modal, Tooltip and Popover. Also be sure to take a look at all the new updates in Bootstrap 5.

What do you think? Do you plan on bringing Bootstrap 5 into your next React project, or do you prefer a different React friendly design system?

Discussion (16)

Collapse
joelnwalkley profile image
Joel N. Walkley

Aren't we supposed to avoid direct interaction with the DOM in a React app? Your useState targets the element directly by name; and also directly adds an event listener. Is there another way to make use of Bootstrap without the 3rd party libraries?

Collapse
carolskelly profile image
Carol Skelly Author • Edited

This is a great question and you're absolutely right! As explained in the React hooks FAQ you'd want useRef in this case. This will ensure we get the .current instance of the DOM element that's synched with the React lifecycle. I've updated the Toast example accordingly...

function ToastDemo() {
    var [toast, setToast] = useState(false);
    const toastRef = useRef();

    useEffect(() => {
        var myToast = toastRef.current
        var bsToast = bootstrap.Toast.getInstance(myToast)

        if (!bsToast) {
            // initialize Toast
            bsToast = new Toast(myToast, {autohide: false})
            // hide after init
            bsToast.hide()
            setToast(false)
        }
        else{
            // toggle
            toast ? bsToast.show() : bsToast.hide()

        }
    })

    return (
    <div className="py-2">
        <button className="btn btn-success" onClick={() => setToast(toast => !toast)}>
            Toast {toast?'hide':'show'}
        </button>
        <div className="toast" role="alert" ref={toastRef}>
            <div className="toast-header">
                <strong className="me-auto">Bootstrap 5</strong>
                <small>4 mins ago</small>
                <button type="button" className="btn-close" onClick={() => setToast(false)} aria-label="Close"></button>
            </div>
            <div className="toast-body">
              ...
            </div>
        </div>
    </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

I also updated the other examples to follow this same pattern.

Collapse
cadday profile image
mt

Thank you for the article, I have checked the examples and still can't be sure if it is okay to use bs components with only data-bs attribute.

Is it a bad practice for React virtual dom to use it like below.


function DropdownDemoBs() {
    return (
        <div class="btn-group">
          <button data-bs-toggle="dropdown" class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuClickableInside" aria-expanded="false">
            Dropdown button bs
          </button>
          <ul class="dropdown-menu" aria-labelledby="dropdownMenuClickableInside">
            <li><a class="dropdown-item" href="#">Menu item</a></li>
            <li><a class="dropdown-item" href="#">Menu item</a></li>
            <li><a class="dropdown-item" href="#">Menu item</a></li>
          </ul>
        </div>
    )
}

Enter fullscreen mode Exit fullscreen mode
Collapse
jbergens profile image
jbergens

For some or maybe most of these examples you should probably also add an empty array for the useEffect dependencies. Basically saying that we only want to run this code once (to create the component), then it does not have to run again as long as the component is left in the DOM tree.

Thread Thread
lgkbsw profile image
lgk-bsw

But then the bsToast.show() or bsToast.hide() wouldn't trigger when the state of toast changes. In my case I only added [toast] to the useEffect dependencies.

Collapse
mamirazmi profile image
m-amirazmi

why the error 'bootstrap' is not defined appear? the bootstrap.Toast give error. where the bootstrap comes from?

Collapse
lgkbsw profile image
lgk-bsw

I did something similar with the Modal component. But I also had to include an event listener when the user clicks outside of the modal to close it:

    useEffect(() => {
        const myModal = modalRef.current as unknown as Element
        let bsModal = Modal.getInstance(myModal)

        if (!bsModal) {
            bsModal = new Modal(myModal)
            bsModal.hide()
            setModal(false)

            // When the user clicks on underlay to close the modal
            myModal.addEventListener("hide.bs.modal", () => {
                setModal(false)
            })
        }
        else {
            modal ? bsModal.show() : bsModal.hide()
        }
    }, [modal])
Enter fullscreen mode Exit fullscreen mode
Collapse
chandu4221 profile image
Chandra Shekhar .D

Please Provide an example for the Dropdown Component.

Collapse
carolskelly profile image
Carol Skelly Author

It works just like the others. See: codeply.com/p/IdzoX6osI2

Collapse
chandu4221 profile image
Chandra Shekhar .D

Thank you.

Collapse
henrychea profile image
Henry Chea

Great explaination and example links ⭐️

Collapse
amitavroy7 profile image
Amitav Roy

Yes, as Joel rightly pointed out what you have done - is it the right way to do things in React?

Collapse
ascensus_mdb profile image
Michal Szymanski

Nice tutorial, thanks.

For those who are looking for ready to use solutions - you can also try out this Bootstrap 5 & React free UI KIT by MDB

mdbootstrap.com/docs/b5/react/

Collapse
ruben profile image
Ruben Santana

For those who are struggling with the navbar and the toggler, here is a good example. dev.to/johnotu/how-to-toggle-boots...

Collapse
omrisama profile image
Omri Gabay

So does this make Reactstrap and React Bootstrap obsolete?

Collapse
carolskelly profile image
Carol Skelly Author

I don't think so, it just makes it possible to use Bootstrap in React in a way that aligns with React patterns/practices.