Using Bootstrap in ReactJS: reactstrap or react-bootstrap?
Cássio Lacerda
Posted on June 2, 2021
It's hard to find developers who have been working with client-side development in the last years, and who haven't at least once used frameworks like Bootstrap, Foundation or Material Design in your frontend projects, to be more productive and save time by reusing pre-made components with ease of customization.
For those who have specifically used Bootstrap for years in development with server-side rendered pages (SSR) and who are now using SPA frameworks like ReactJS, it's normal to start looking for alternative packages in the NPM directory that make it easier to use the built-in Bootstrap with ReactJS.
If you've arrived here, you've probably already researched that the two most popular alternatives within this scenario today are React Bootstrap
and Reactstrap
. But what's the difference between them? Are they significant?
Official documentations:
Both work in the same way, from the perspective of use:
- They need
npm install bootstrap
to import Bootstrap stylesheet file inside index.js or App.js to enable Bootstrap default styling withimport 'bootstrap/dist/css/bootstrap.min.css';
. ReactJS, by default, will append all Bootstrap CSS code in a style tag inside head of HTML page.
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
rootElement
);
- Give us ready-to-use Bootstrap Components redesigned internally as JSX, without the need to use JQuery or Javascript with direct DOM manipulation (using Virtual DOM, as React already works by default);
- Behind the scenes, using
React.createElement
to render the components;
Props
The props passed to the components can have different names depending on the package. See the Button color usage: https://codesandbox.io/s/reactbootstrapvsreactstrap-7y87c-7y87c?file=/src/App.js
import React from "react";
import { Button as ReactBootstrapButton } from "react-bootstrap";
import { Button as ReactstrapButton } from "reactstrap";
const App = () => (
<>
<ReactBootstrapButton variant="danger">React BootStrap</ReactBootstrapButton>
<ReactstrapButton color="danger">Reactstrap</ReactstrapButton>
</>
);
export default App;
The props names are different color
and variant
, but rendered HTML is pretty much the same, as we can see in DevTools:
Behind the scenes
You can view both implementations, comparing a basic component as Button
in the packages source code:
- node_modules\react-bootstrap\cjs\Button.js (React Bootstrap ^1.6.0);
- node_modules\reactstrap\dist\reactstrap.cjs.js line:930 (Reactstrap v^8.9.0);
React Bootstrap
var Button = /*#__PURE__*/_react.default.forwardRef(function (_ref, ref) {
var bsPrefix = _ref.bsPrefix,
variant = _ref.variant,
size = _ref.size,
active = _ref.active,
className = _ref.className,
block = _ref.block,
type = _ref.type,
as = _ref.as,
props = (0, _objectWithoutPropertiesLoose2.default)(_ref, ["bsPrefix", "variant", "size", "active", "className", "block", "type", "as"]);
var prefix = (0, _ThemeProvider.useBootstrapPrefix)(bsPrefix, 'btn');
var classes = (0, _classnames.default)(className, prefix, active && 'active', variant && prefix + "-" + variant, block && prefix + "-block", size && prefix + "-" + size);
if (props.href) {
return /*#__PURE__*/_react.default.createElement(_SafeAnchor.default, (0, _extends2.default)({}, props, {
as: as,
ref: ref,
className: (0, _classnames.default)(classes, props.disabled && 'disabled')
}));
}
if (ref) {
props.ref = ref;
}
if (type) {
props.type = type;
} else if (!as) {
props.type = 'button';
}
var Component = as || 'button';
return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({}, props, {
className: classes
}));
});
Button.displayName = 'Button';
Button.defaultProps = defaultProps;
var _default = Button;
exports.default = _default;
module.exports = exports["default"];
Reactstrap
var Button = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(Button, _React$Component);
function Button(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_this.onClick = _this.onClick.bind(_assertThisInitialized(_this));
return _this;
}
var _proto = Button.prototype;
_proto.onClick = function onClick(e) {
if (this.props.disabled) {
e.preventDefault();
return;
}
if (this.props.onClick) {
return this.props.onClick(e);
}
};
_proto.render = function render() {
var _this$props = this.props,
active = _this$props.active,
ariaLabel = _this$props['aria-label'],
block = _this$props.block,
className = _this$props.className,
close = _this$props.close,
cssModule = _this$props.cssModule,
color = _this$props.color,
outline = _this$props.outline,
size = _this$props.size,
Tag = _this$props.tag,
innerRef = _this$props.innerRef,
attributes = _objectWithoutPropertiesLoose(_this$props, ["active", "aria-label", "block", "className", "close", "cssModule", "color", "outline", "size", "tag", "innerRef"]);
if (close && typeof attributes.children === 'undefined') {
attributes.children = /*#__PURE__*/React__default.createElement("span", {
"aria-hidden": true
}, "\xD7");
}
var btnOutlineColor = "btn" + (outline ? '-outline' : '') + "-" + color;
var classes = mapToCssModules(classNames(className, {
close: close
}, close || 'btn', close || btnOutlineColor, size ? "btn-" + size : false, block ? 'btn-block' : false, {
active: active,
disabled: this.props.disabled
}), cssModule);
if (attributes.href && Tag === 'button') {
Tag = 'a';
}
var defaultAriaLabel = close ? 'Close' : null;
return /*#__PURE__*/React__default.createElement(Tag, _extends({
type: Tag === 'button' && attributes.onClick ? 'button' : undefined
}, attributes, {
className: classes,
ref: innerRef,
onClick: this.onClick,
"aria-label": ariaLabel || defaultAriaLabel
}));
};
return Button;
}(React__default.Component);
Despite some differences such as the approach with the use of prototype that reactstrap
implements, and specifically in this component, the handling of some additional props, in general, there are no significant differences between them.
Components List
Available components are 80% to 90% the same, and some of them just have different names.
React Bootstrap: Alerts, Accordion, Badge, Breadcrumb, Buttons, Button Group, Cards, Carousel, Dropdowns, Figures, Forms, Input Group, Images, Jumbotron, List Group, Modal, Navs, Navbar, Overlays, Pagination, Popovers, Progress, Spinners, Table, Tabs, Tooltips, Toasts.
Reactstrap: Alerts, Badge, Breadcrumbs, Button Dropdown, Button Group, Buttons, Card, Carousel, Collapse, Dropdowns, Fade, Form, Input Group, Jumbotron, Layout, List, List Group, Media, Modals, Navbar, Navs, Pagination, Popovers, Progress, Spinners, Tables, Tabs, Toasts, Tooltips.
You can find out how to use them all in the official documentations showed previously in this post.
Differences so far? Very few ... I'm still undecided ...
You're not the only one. Relax!
To be honest, just the numbers show any significant difference here. Adoption of React Bootstrap is higher.
https://www.npmtrends.com/react-bootstrap-vs-reactstrap
OK, it's older and it maybe makes the difference.
More numbers here:
https://npmcompare.com/compare/react-bootstrap,reactstrap
And you?
I worked with both of them, but I particularly like to use React Bootstrap, but not because of a Reactstrap deficiency, but because I have been using it for a while and have always attended to my needs. Don't you like Bootstrap? Do you prefer another component library? Yes? I like another libraries too, but that is subject to another post.
If you have any special reasons for using React Bootstrap or Reactstrap, if you know any significant performance differences, help the Community and share in the comments!
Posted on June 2, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.