DEV Community

Discussion on: Using Bootstrap 5 with React

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
 
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
 
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
 
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