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