What I learned from publishing my First NPM React package
Tags: npm, react, programming, css
Published: 2020-12-13 12:04:20

## Introduction
I published my first React UI Wrapper on NPM. You can find the package below:

https://www.npmjs.com/package/react-horizontal-scroll-grid

It is a simple Ui wrapper which helps you to create horizontal scroll view. I was inspired by Netflix, Amazon and other online video streaming apps to create this package. For Example consider the Netflix app, it has this sleek horizontal scroll with movie/TV show titles in it.

![](https://miro.medium.com/max/5540/1*I0e-CselYjM4wxp7AHMlTQ.png)

I bumped into many ups and downs while creating this package. I would like to share the same with everyone.

## Approach

#### Step 1: CRA to rescue
Since I am a newbie to react so my first step for creating this package was to use `create-react-app`. So for any react-developer this is the most common step:
```
npx create-react-app <project-name>
```
The above command created a ready-to-go react project within minutes. Later I realized this was the worst thing I did. Later on this in **Pitfalls** section.

#### Step 2: Writing code logic
The code logic behind the package is pretty straight forward. Before diving into code logic I am assuming that you guys have knowledge of ![css-grids](https://css-tricks.com/snippets/css/complete-guide-grid/). The `HScrollGrid` is the UI Component name in our package that is wrapped around couple of `<li>` HTML tags. Below is the code logic for `HScrollGrid`:
```javascript
class HScrollGrid extends React.Component{
    constructor(props){
        super(props);

        this.hscrollRef = React.createRef();
    }

    componentDidMount(){
        let n = this.hscrollRef.current ? this.hscrollRef.current.children.length : 0;
        let gW = `${this.props.gridWidth}px`;
        let gH = `${this.props.gridHeight}px`;
        let cW = `${this.props.cardWidth}px`;
        let cardBgColor = this.props.backgroundColor ? this.props.backgroundColor : 'transparent';

        if(this.hscrollRef.current){
            this.hscrollRef.current.style.setProperty('--total', n);
            this.hscrollRef.current.style.setProperty('--gridWidth', gW);
            this.hscrollRef.current.style.setProperty('--gridHeight', gH);
            this.hscrollRef.current.style.setProperty('--cardWidth', cW);
            this.hscrollRef.current.style.setProperty('--cBgCol', cardBgColor);
        }
    }
    render(){
        return(
            <ul className="hscroll-grid" data-testid="test-ul" ref={this.hscrollRef}>
                {this.props.children}
            </ul>
        );
    }
}
```
I am using css-variables in the react component to pass in the values back to css properties. The advantage I have over here is, now I can dynamically pass the props of the component to css properties. Below is the css code for grid layout. Notice how I have used the css-variables pass down via the `HScrollGrid` component as a prop:

```css
ul.hscroll-grid{
    width:var(--gridWidth);
    height: var(--gridHeight);

    display:grid;
    grid-template-columns: repeat(var(--total), var(--cardWidth)) 10px;
    grid-column-gap: 20px;

    overflow-x:scroll;
    overflow-y:hidden;
}   

li{
    width: var(--cardWidth);
    height: var(--gridHeight);
    background-color: var(--cBgCol);
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;

    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.1);
    transition: 0.3s;
}

li:hover{
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}
```

### Pitfalls
* The first mistake I did was to choose CRA for creating an npm package. As I am aware, that a package should have least amount of dependencies on other packages. Over here since we have used CRA therefore it comes with a lot of pre-installed dependencies that are not required.
I faced some serious issues related to package broken error on different systems and environments. To solve this I googled a lot of things related to the keyword `dependencies` and `dev-dependencies`. Found the following two to be most relevant:
    1. Remove additional(not required) dependencies manually which are found under `dependencies` key of `package.json` file.
    2. To do: `npm run eject`


    I ended up with the former approach i.e. Remove additional dependencies. I did not use the latter approach because I ran into breaking the entire code :(
 <br/>


* Second mistake was choosing CRA: `npm run build` command minified all the code present in all component files and clubbed them together. I found this to be quite annoying because I just wanted to transpile all my `HScrollGrid` component code into es5 so that it is support by majority of the browsers. And also I just wanted this single component file to be processed whenever I ran `build` command. To solve this I had the following sub-approaches:
<br>
    * Either I do `npm run eject` and modify `webpack.config.js`.
    OR
    * I edit the `build` command to make use of `babel-cli` command to transpile my component files into one `lib` folder.

    <br/>

    I choose the latter option because it was less time consuming. I know this is a dirty fix and not at all recommended but I was too excited to roll out my first NPM Package :)

## Publishing to NPM

After all the dirty fixes and chaos I manged to pull off the package. I tested it first locally and then published it on NPM. 

Publishing a package on NPM was easy. You need to get yourself registered on [npm](https://www.npmjs.com/). Post that you will need to login via CLI in your local system:

```
npm login
```

After publishing all your commits to your repository you can simply enter following command to publish the package on NPM:

```
npm publish
```

## Final thoughts
It was an awesome experience in publishing the first NPM public package. I am planning to focus on building more packges. 

This journey taught me lots of new things such as: CRA-boiler plate code, cons of using CRA, creating production grade code, understanding and editing various config files such as: webpack.config.js, package.json etc.

Feel free to contact me about the problems. I will try to help as much as I can 😉

<div style="display:flex;flex-direction:row;justify-content:center">

[![Linkedin Badge](https://img.shields.io/badge/linkedin-%230077B5.svg?&style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/keyur-paralkar-494415107/)

[![Mail Badge](https://img.shields.io/badge/email-c14438?style=for-the-badge&logo=Gmail&logoColor=white&link=mailto:furkanozbek1995@gmail.com)](mailto:keur.plkar@gmail.com)

[![Twitter Badge](https://img.shields.io/badge/twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white)](https://twitter.com/keurplkar)

[![Github Badge](https://img.shields.io/badge/github-333?style=for-the-badge&logo=github&logoColor=white)](https://github.com/keyurparalkar/)

</div>