DEV Community

Cover image for Using Bootstrap 5 with React

Using Bootstrap 5 with React

Carol Skelly on December 30, 2020

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 i...
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 • 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
 
amirazmi profile image
Muhamad Amir Azmi

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

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

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