Skip to content

Instantly share code, notes, and snippets.

@dayhaysoos
Last active February 19, 2021 18:07
Show Gist options
  • Save dayhaysoos/d57acc0ad69c42cf974ae57cd34ca1f5 to your computer and use it in GitHub Desktop.
Save dayhaysoos/d57acc0ad69c42cf974ae57cd34ca1f5 to your computer and use it in GitHub Desktop.
# Create your own hooks library
When I first started learning how to code, I never considered the possibility of being an open-source maintainer. I didn't think I'd be smart enough to provide something truly valuable, I also wasn't in a position where I could afford to spend time on anything like that for free. Thanks to GitHub sponsors, the latter isn't so much of an issue anymore!
There are lots of great reasons to kick off and maintain your own library, but I'd like to lead with the number one reason how I ended up doing it "by accident".
I maintain a library called [use-shopping-cart](https://useshoppingcart.com), a Stripe powered, React Hooks library that handles your shopping cart state and logic. I once wanted to launch a swag store and figured I'd roll my own e-commece experience. Little did I know how much work that would entail. I was so frustrated with it that I told myself I never want to write out this logic ever again. I did *not* expect to be in a place where I'm getting sponsorships, and people are adopting this library for real businesses!
I'd like to share what I used to kick off this library and some things to consider when kicking off your own library. Mind you, this blog caters to those who know and are familiar with React.
## Getting started
Install create-react-hook with this command:
`npm install -g create-react-hook`
You can see the repo here: https://github.com/Hermanya/create-react-hook
Here are some of the features on the ReadMe that are nice to have
### Features
- Easy-to-use CLI
- [Rollup](https://rollupjs.org/) for bundling
```
Rollup allows you to write your code using the new module system, and will then compile it back down to existing supported formats such as CommonJS modules, AMD modules, and IIFE-style scripts. This means that you get to write future-proof code, and you also get tremendous benefits.
```
- [Jest](https://facebook.github.io/jest/) for testing
Jest is a testing framework that makes testing JavaScript easier
To start a new project, run:
`create-react-hook`
You'll go through some basic prompts. I chose `yarn` for the package manager because I wanted to take advantage of yarn workspaces. At the time, npm didn't support workspaces but it does now.
Workspaces allow you run commands for multiple packages from the root directory. That way you don't have to navigate to each package to run your commands. I will walk you through refactoring this project so you can have it set up for workspaces.
First thing you should do is make a new directory for your library code to live. By default that's the `src` directory. I made a new directory called `use-shopping-cart` and dragged the `src` folder into it. Make sure you also drag the `package.json`, `rollup.config.js`, `.babelrc`, `.eslintrc` and `.prettierrc` that are at the root directory into your new folder as well since your library will rely on those.
Your root directory shouldn't have a `package.json` at this point, you have to make a new one. Run `npm init` and go through the prompts to set up a new `package.json`
To properly set up a workspace with yarn, you have to add two keys to your top level `package.json`
```json
{
"private": true,
"workspaces": [
"examples/*",
"use-shopping-cart",
"documentation"
],
}
```
Workspaces takes an array of package names. You can either use `/*` to make every package inside the directory a workspace or you can add the package name itself. The example directory came with `create-react-hook`, I renamed it to `examples` since I plan on having more than one package in there (you don't have to do this). The `use-shopping-cart` directory is where the library code lives and I also have `documentation` directory.
*NOTE* `create-react-hook` makes a package.json in your example for you called that is the name of your library with `-example` at the end. So for USC, it was `use-shopping-cart-example`. You might want to replace the `"examples/*` line with that convention if you don't plan on having multiple examples.
If you go to the root directory and run: `yarn workspaces info` you should get back a list of workspaces recognized by yarn. If you don't see a package you were expecting, double check to make sure it has a package.json file with the `name` with whatever the name your package is.
One other thing you should probably do is delete *all* node_module folders and run `yarn install` at the root directory. From what I understand, this creates one `node_modules` folder to rule them all, and all the packages that rely on it will be referrencing that instead of having a bunch of dense `node_modules` folders everywhere.
If I wanted to run tests for use-shopping-cart from the root directory, I could run:
`yarn workspace use-shopping-cart test:watch`
Instead of navigating to the folder.
Another really nice perk is how you can test your library on the client side!
If you go to your example project and add this to dependencies:
```json
"dependencies": {
"use-shopping-cart": "*"
},
```
What this does is refer to the package local to the project, making it aware of any changes you may have made without having to upload to `npm`.
This set up process isn't that fun but I promise that you'd save tons of time with something like this.
### Extra things added to use-shopping-cart:
- `prettier` for formatting
- [husky](https://github.com/typicode/husky/tree/master) pre-commit hooks
- [lint-staged](https://github.com/okonet/lint-staged) to run the linter on staged files (via husky)
The config for this is pretty straight forward, here is what it looks like in the `use-shopping-cart` root package.json:
```json
"dependencies": {
"husky": "^4.2.5",
"lint-staged": "^10.2.0",
"prettier": "^2.0.5",
"shx": "^0.3.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,.d.ts,ts,tsx,mdx}": "prettier --write"
},
```
Husky is running `lint-staged` on `pre-commit` to make sure that no matter what anyone has for lint config locally, that everything stays the same format on the repo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment