In React, a reusable component is a piece of UI that can be used in various
parts of an application to build more than one UI instance.
For instance, we can have a Button
component that displays different texts on
different pages. Generally speaking, we can make a component more reusable by
turning it from more specific to more generic.
Features
Let us create the following components in this chapter. We will make each of
these components reusable with the help of props:
- NavBar
- Table
- Input
- Button
- PageLoader
- PageTitle
- Tooltip
Technical design
In this chapter we will make the following changes:
-
We will be creating a reusable Button
component. In our Button component, we
will provide options to update the type
of the button
and the handler for
the button events. Along with that, we will also provide a loading
option,
which comes in handy when submitting a form.
-
While naming the components, we will follow PascalCase
for naming both the
exported component as well as the filename.
-
Create a PageTitle
component that will display the given title
for each page.
-
Create a NavBar
Component that will display a logo
of our project,
a link to Todos
and an Add new task
button.
-
We will add remixicon
package to the project, which will allow us to use
icons by specifying the icon code in the class names of an HTML tag.
-
We will be adding a reusable Input
component. In that we will have options
to give the type
of the input and the handler for the input change events.
Along with that, we will also provide a label
and placeholder
options.
-
There are cases where the page can't be rendered yet due to invalid data or
due to not receiving a response from an API call. In such situations to let
the user know that the page is loading, we will create a PageLoader
component.
-
We need a visually understandable structure for listing tasks along with their
details and corresponding icons. For that let's create a reusable Table
component that will consist of Row
s and a Header
.
-
We also need a Tooltip
component to view the full title of a Task if it gets
truncated due to its length.
We are now ready to move to the implementation part. Let us dive in.
Custom Tailwind colors
We will be using, custom defined color classes to style our components. To do
so, add the following lines of code to tailwind.config.js
:
Install Ramda
We recommend using Ramda library over
lodash for most of the JavaScript operations and helpers
since it's well maintained, functional and lightweight.
In general when checking whether a variable is null
/empty
etc, use the
isNil
/isEmpty
functions from ramda
. Similarly Ramda functions are highly
extensile and importantly reusable.
Install ramda
first:
Install classnames
We are going to use a library called classnames
in components. It is a
JavaScript library for conditionally joining CSS classes together.
React terms these joined attributes as classNames
.
We use this library extensively in most of our projects and thus will be using
the same throughout this book.
Install classnames
package by running the following command:
Add remixicon to dependencies
To display icons in our application, we will install a third-party package
called remixicon. This library has a lot of icons
which we can use in our code. We are not required to import the icons in our
components.
Run the below command to add remixicon
package:
We also need to add the remixicon CSS to our JavaScript stylesheets to properly
render the icons.
Append the following lines to app/javascript/stylesheets/application.scss
:
Button component
We will keep the commonly used components in the app/javascript/src/components/commons
folder. Run the following command to create the Button
component file inside the commons
folder:
In Button.jsx
paste the following content:
GraniteLogo component
Let's create a GraniteLogo
component to display a logo for our project as shown below:
We need to display the GraniteLogo
as part of the NavBar
. Create the GraniteLogo
component inside the NavBar
folder:
Add the following lines to GraniteLogo.jsx
file:
You can design logos using tools like Figma and return the corresponding svg
as a reusable component like this.
NavBar component
Let's create the NavBar
reusable component:
It's named index.jsx
because it's the root file which will be auto-imported in
scenarios where we import like say import NavBar from '../NavBar'
.
In index.jsx
, paste the following content:
Container component
To create a Container
component, run the following command:
Now, open the Container.jsx
file and paste the following
content:
Input component
To create an Input
component, run the following command:
In Input.jsx
, paste the following content:
Tooltip Component
We will make use the @floating-ui
package to build the Tooltip
component.
Run the following command to add @floating-ui
package:
Create the Tooltip
component file by running the following command:
In Tooltip.jsx
, paste the following content:
Table component
To create a Table
component, we will create Row
and Header
components:
In Row.jsx
, paste the following content:
Create Header
component by running the following command:
In Header.jsx
, parse the following content:
Now, create an index.jsx
file inside the Table
folder by running the
following command:
Paste the following content in Table/index.jsx
:
Now, Table
can be imported by using following line:
PageLoader component
To create a PageLoader
component, run the following command:
In PageLoader.jsx
, paste the following content:
PageTitle component
To create a PageTitle
component, run the following command:
In PageTitle.jsx
, paste the following content:
Now that we have defined the common components like Button
, Container
, etc, we will add an index.js
file to export all the components from the commons
folder together. This will help us avoid multiple imports, as shown below:
Instead we can import the components in a single import:
Add the following lines to index.js
file:
Now let's commit these changes: