Adebola's Blog

How to publish a Custom react hooks package written in TypeScript.

August 06, 2020

First , The Config

  1. To get started, you can either have TypeScript installed globally on your computer using sudo apt install node-typescript for Linux or you can have it installed as a Dev Dependency using npm i typescript --save-dev. We only need TypeScript for development and not in the published code.

    Personally, I prefer to have TypeScript installed globally on my machine.

  2. Next, create a folder called react-direction. Navigate into that folder and run npm init -y. This will generate a package.json file automatically!
  3. Next, run tsc --init. Running tsc --init will generate a tsconfig.json file for you. Update it to look like below.
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": ["es2017", "es7", "es6", "dom"],
    "outDir": "./lib",
    "declaration": true,
    "strict": true,
    "esModuleInterop": true
  },
  "exclude": ["node_modules"]
}
  1. Target tells the compiler what version of JavaScript we want our code to compile to. Lib tells the compiler what versions of JavaScript we will be writing. By specifying ./lib as our outDir and "declaration": true, TypeScript will compile both our type definitions and final(es5) JavaScript code into the a new folder called lib.
  2. Add main, types and prepublish options to your package.json like below. The types option points to our type declarations, while the main option points to our compiled JavaScript file.

Our package.json should now look like below.

{
  "name": "react-direction",
  "version": "1.0.0",
  "description": "An npm package that allows you get the most up-to-date position when a user clicks on a previous/next button.",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "prepublish": "tsc",
  "scripts": {
    "build": "tsc"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/onedebos/react-direction.git"
  },
  "author": "Adebola Adeniran",
  "files": ["lib/**/*"]
}

The file generated from the main option ensures that anyone can run our package since it’s running on es5 while the file generated by the types option ensures that if the user of our package is using TypeScript, they will also be able to use the power of type definitions. The build command is to make sure if we run npm run build , our code is compiled into JavaScript.

We will use a files option inside our package.json to whitelist files we want to send to NPM rather than using a .npmignore.

  1. When we’re done writing our package, we can run tsc or npm run build to compile our files into JavaScript.

Writing our Custom Hook

I noticed I build a lot of mini-navigations that use Previous and Next buttons. I decided that I needed a way to be able to re-use that code inside my react components. I needed a way to keep track of what position in a list the User is when they click Previous or Next so that I can update the DOM accordingly.

Enter the useDirection hook! You can call yours anything. This is just the name I decided on.

This is what we’ll be building today.

With everything setup from above, in the root of our react-direction folder, create an index.ts file.

Setup the Custom hooks

  1. Install react using npm i react.
  2. Initialize git by running git init.
  3. Create a .gitignore file and put your nodemodules_ folder in it. This ensures that our nodemodules_ folder isn’t published to Github. We also don’t want our compiled code to be published to git, so add lib to .gitignore.
  4. Finally, let’s write the code for our Custom hook using TypeScript. In the index.ts file at the root of the application, add the following code.
import { useState, useRef } from "react";
const useDirection = (totalPages: number) => {
  const [now, setNow] = useState<number>(1);
  const ref = useRef<number>(1);
const goBack = () => {
    ref.current -= 1;
    if (ref.current < 1) {
      ref.current = 1;
      return;
    } else {
      setNow(ref.current);
    }
  };
const goForward = () => {
    ref.current += 1;
    if (ref.current > totalPages) {
      ref.current = totalPages;
      return;
    } else {
      setNow(ref.current);
    }
  };
return [now, goBack, goForward] as const;
};
export default useDirection;

Once done, run tsc or npm run build to compile our code into JavaScript and to also create our generate our types/type definitions.

NB: If building an NPM package specifically for React, I prefer to remove React as a dependency before publishing to NPM. I noticed that Create-React-App has a bug that pops up when there is more than 1 version of React installed.

You may see something like the error below.

Hook Error: Hooks can only be called inside the body of a function component

To avoid this when done developing and tesing, Make sure to delete React from your dependency list inside your package.json file.

  1. Finally, let’s test our code. First run npm link from your command line and in the root of the react-direction package. Then inside an already existing React application where you wish to test out the package, run npm link react-direction.
  2. Import useDirection from 'react-direction'. Use it! and Enjoy!
  3. Once you confirm that everything works, run npm publish in the terminal/command line from the react-direction folder to publish the package to NPM.

Well I already own that name so you’ll need to choose another:).


Written by Adebola Adeniran, I love Nigerian Jollof (> Ghana jollof) and Plantain. Follow me on Twitter.