Build Scalable React Apps by Sharing UIs and Hooks
How to build scalable React apps with independent and shareable UI components and hooks.
In this demo, we’ll use Bit to manage our app’s components and hooks as discrete, independent, and shareable building blocks.
Bit offers us:
- A component-level source-control (alongside our project source-control)
- Isolated component testings (i.e, isolated from the rest of the project)
- A platform to inspect a component’s behavior across contexts (i.e, in different compositions)
- An easy way to document, package and publish individual components
We’ll be using Bit in combination with Bit's cloud service — Bit.dev (which is also free, for most uses). You may also choose to use your own server, instead.
Short demo: Building and sharing independent UIs and hooks
Our “jokes app” will be made of a button component, a hook, and the composition of the two. We’ll use create-react-app to get started.
$ npx create-react-app jokes-app --template typescript
Creating the button (UI) component
The button component file structure:
|-- src
|-- ui
|-- button
|-- button.tsx
|-- button.module.scss
|-- button.spec.js
|-- button.ts
Inside button.tsx
:
The above JSDocs comments and TypeScript definitions would be used by Bit to generate the documentation for that component. This documentation would be part of the component page on Bit.dev.
The index.tsc
file will export everything, like so:
export * from './button.tsx
Creating the useGetJokes hook
React 16.8’s Hooks have made sharing logic, easier than ever. No need for cumbersome Higher-Order Components or Render Props. Logic is now decoupled from UI and shared between components as elegant Hook functions. Hooks should be thought of as basic (logic) building blocks for our React apps.
The useGetJokes
hook will fetch and handle jokes from a jokes API.
|-- src
|-- hooks
|-- useGetJokes
|-- useGetJokes.ts
|-- useGetJokes.spec.js
|-- index.ts
Inside the useGetJokes.tsx
file:
Share components to Bit.dev
Install Bit and initialize a Bit workspace:
$ npm i bit-bin -g
$ cd bad-jokes
$ bit init
Start tracking our components (we’ll also use the -n
flag to namespace each of them):
$ bit add src/ui/button -n ui
$ bit add src/hooks/use-get-jokes -n hooks
Configure a compiler for our components (remember, they need to be decoupled from our project’s build/bundle setup).
For other compilers, see here.
$ bit import bit.envs/compilers/react-typescript --compiler
Tag our components (commit a component version, test, build, and package):
$ bit tag --all 1.0.0
The tagged components are packaged as individual packages, not as a library! The
--all
flag is used here as a shorthand to tag both with a single version.
Register to Bit.dev (this is the default remote server for Bit) and create a “collection” for our soon-to-be-published components.
Login to Bit.dev (in the terminal):
$ bit login
Export (publish) components:
$ bit export <username>.<collection-name>// for example:
// bit export eden.jokes-app
The button component and useGetJokes hook are now available to be installed as independent components.
In my collection, I’ve added examples for each. Check it out here:
Import/Install published components
You can install your published packages (the hook or the button) as regular NPM packages, or you can “import” them using Bit.
“Imported” components are (sort-of) cloned into your project. That means you can change their code, tag them with a new version, and “push” them back to their collection.
For example, let’s import the useGetJokes
hook from my collection:
$ cd path/to/new/project
$ bit init
$ bit import eden.jokes-app/hooks/use-get-jokes
It is now available in:
(root)
|-- components
|-- hooks
|-- use-get-jokes
There’s also a symbolic link in the node_modules folder:
|-- node_modules
|-- @bit
|-- eden.jokes-app.use-get-jokes
You can use bit watch
to modify the hook (in the components
directory) and use its (auto-built) dist in your project.
Conclusion
Hooks and UI components are the basic building blocks of a React application. By sharing them using Bit, we can build maintainable and scalable apps. We can also enjoy faster delivery (as less gets re-written), and maintain a consistent UI/UX.
Unlike standard packages, components shared with Bit are independently source-controlled and packaged. That makes every project part of a “virtual monorepo” (only without the usual overhead).