31Aug
How To Careate a React Ccomponent Library - Using a Modal Example
How To Careate a React Ccomponent Library – Using a Modal Example

Components allow us to break applications into smaller pieces that can be worked on independently. Another good thing about them is that they allow us to reuse logic. Such components will be able to be used in (and with) several other components across the application.

When working on a project, you can simply store the components in a components folder where all pages and components within your project can access it.

But, have you ever found yourself needing a very component you use all the time across different projects? Where you’d have to copy and paste the component’s file or folder into another codebase?

Instead of doing this, you can have your own React library. Tools like Chakra UI and Material UI are React component libraries that can be adopted by any react project.

However, creating a react library is different from how you normally would for a component within a project.

Here’s an example of creating a component in a project:

import React from 'react'

const Input = props => {
  const {label, placeholder} = props;

  return <div>
    <label htmlFor={label}>{label}</label>
    <input id={label} placeholder={placeholder} />
  </div>
}

export default Input

This is just okay for a project-based component. The above is code for development and cannot be used directly in production.

For a library, the components created would have to be processed into production code which can be then adopted by other applications.

As we continue in this article, we’ll learn how to create a component library using a Modal example.

How to create a Modal component Library

For this example, we are going to create a modal component that would be exported from the library.

Firstly, we would need to set up our environment. There are few ways to create a react library but I’ve found create-react-library to be seamless and easily customizable.

create-react-library supports typescript, CSS modules, Babel for transpiling, and Jest to name a few.

Let’s get started building our library.

Install Library

npm i -g create-react-library

This command would install the library globally in your device. If you do not want it this way, here’s an alternative:

npx create-react-library

The above would be executed when you want to start the project. With npx, the library would not be installed globally but used directly (from the source) to create your project folder.

Create the project folder

For this example, we’ll stick with react-modal as the name of our project.

You may want to change the name to something else if you intend on publishing it on npm because npm has unique names for packages.

If you installed the library globally, create a project by doing so:

create-react-library react-modal

Else,

npx create-react-library react-modal

The above command would display a list of options which are:

* The template can be default (which is JavaScript), typescript or custom. For this example, we’ll use default.

After filling in your answers, the library would create your folder, install the required dependencies set up default files for your library. Here’s the tree structure:

react-modal/
├── dist
├── example
├── node_modules
├── package.json
├── package-lock.json
├── README.md
└── src

On install, the library creates an src directory which contains the files for the library, a dist directory which contains the production code of the library and an example directory which contains codes that use the library we are making. This way, we can make changes to the library and simultaneously visualize the result when in use.

See it this way: src directory is the library in development and example directory is the library in production (which uses the codes in the dist directory).

Start server

The only directory that would require a server is the example directory because that is where we preview the result. There’s nothing to preview in the src directory as the library on its own is a utility and not an application.

However, the src/package.json file also has a start script which watches for change in the library and automatically builds the production code of the library in dist.

The following are commands to run to get started:

npm start # start script for the library
cd example # change directory
npm start # start server for example application

Here’s is the webpage on localhost:3000:

Screenshot of the default webpage created using create-react-library
Screenshot of the default webpage created using create-react-library

The example directory uses the default component created by the library.

Here’s the default component:

import React from 'react'
import styles from './styles.module.css'

export const ExampleComponent = ({ text }) => {
   return <div className={styles.test}>Example Component: {text}</div>
}

Here’s how it is used in example/src/App.js:

import React from 'react'

import { ExampleComponent } from 'react-modal'
import 'react-modal/dist/index.css'

const App = () => {
   return <ExampleComponent text="Create React Library Example :)" />
}

export default App

If you notice in the image above, the component and its stylesheet had to be imported together. That may appear ugly as you would always need those two imports for just one component.

An alternative to this is having inline styles. That is what we would use in the component. Also, you can use libraries like styled-components which support CSS in JS.

Let’s create the Modal component

The features of the modal component are very simple:

  • it can contain anything
  • it has a close button
  • it shows a backdrop overlay when open

Firstly, let’s create the Backdrop component:

// src/backdrop.js
import React from 'react'

const backdropStyles = {
  position: 'fixed',
  left: 0,
  top: 0,
  width: '100%',
  height: '100vh',
  backgroundColor: 'rgba(0, 0, 0, 0.472)'
}

const Backdrop = ({ onClick }) => {
  return <div onClick={onClick} style={backdropStyles} />
}

export default Backdrop

This component receives an onClick prop which we would use to close the modal.

The code for the modal component is as follows:

// src/index.js
import React, { Fragment } from 'react'
import Backdrop from './backdrop'

const wrapperStyles = {
  width: '100%',
  position: 'absolute',
  left: 0,
  top: 0
}

const modalStyles = {
  maxWidth: '500px',
  width: '100%',
  border: '1px solid #ddd',
  backgroundColor: 'white',
  margin: '100px auto 0',
  zIndex: 1,
  position: 'relative',
  padding: '10px'
}

const closeBtnStyles = {
  position: 'absolute',
  right: '20px',
  top: '20px',
  background: 'none',
  border: 'none',
  fontWeight: 'bold',
  fontSize: '20px',
  cursor: 'pointer'
}

const Modal = ({ children, show, onClickCloseBtn }) => {
  return (
    <Fragment>
      {show && (
        <div style={wrapperStyles}>
          <Backdrop onClick={onClickCloseBtn} />
          <div style={modalStyles}>
            <button onClick={onClickCloseBtn} style={closeBtnStyles}>
              X
            </button>
            {children}
          </div>
        </div>
      )}
    </Fragment>
  )
}

export default Modal

The modal component receives three props: children, show and onClickCloseBtn.

* children is the content that appears between `<Modal>` and `</Modal>`.
* show is a boolean which we use to determine if the modal should show or not. Alternatively, this can be handled from the parent component.
* onClickCloseBtn is a function that the parent component handles when the backdrop or close button of the modal is clicked. As you would have guessed, this would be used to close the modal.

Now, let’s use the component in the example directory:

// example/src/App.js
import React, { useState } from 'react'
import Modal from 'react-modal'

const App = () => {
  const [showModal, setShowModal] = useState(false)

  const hideModal = () => showModal && setShowModal(false)

  return (
    <div>
      <h1 style={{ textAlign: 'center', padding: '10px' }}>react-modal</h1>
      <button
        style={{
          width: '200px',
          display: 'block',
          margin: '0 auto',
          padding: '10px',
          background: 'none',
          border: 'none',
          backgroundColor: '#eee',
          fontSize: '20px',
          cursor: 'pointer'
        }}
        onClick={() => setShowModal(true)}
      >
        Show Modal
      </button>
      <Modal show={showModal} onClickCloseBtn={hideModal}>
        <h1>I am a modal</h1>
      </Modal>
    </div>
  )
}

export default App

Here’s the result:

Preview of the example application using the Modal component
Preview of the example application using the Modal component

When the button is clicked, here’s the result:

Preview of the example application using the Modal component when the show button is clicked
Preview of the example application using the Modal component when the show button is clicked

You’ll notice the faded backdrop. On clicking it or the close button of the modal, the modal closes.

Here’s the source code on GitHub

Wrap up

This article explains how to create a react component library using create-react-library and using a Modal example.

Although the example used here was minimal, I hope this gives you a full understanding of how it works and how you can make your own complex and reusable components.

Rendering Patterns: Static and Dynamic Rendering in Nextjs

Next.js is popular for its seamless support of static site generation (SSG) and server-side rendering (SSR), which offers developers the flexibility to choose the most appropriate rendering method for each application page. Traditionally, Next.js utilized functions like getStaticProps, getStaticPaths, and getServerSideProps to manage how pages are rendered. Depending on the data requirements, these functions determine whether a page should be generated at build time or on each server request.

Leave a Reply