This is first post on this blog – I hope it will be useful for all of you. The idea for it started when I had a lot of pain and headache with creating package with react component for npm with react hooks. Let start it!

First step – initialize package:

At the beginning we need a proper name for our package. Let start with react-component-wolesblog name.

npm init react-component-wolesblog
cd react-component-wolesblog
npm init

At this point we need to go trough the npm wizard. Now before testing any publish we need to have npm user account (Sing in) and be logged in:

npm login

Now we are good for first try to publish our new created package:

npm publish

After that step we should be able to see new package in our npm profile page under the tab Packages

Second step – add typescript

npm install typescript --save-dev

To create tsconfig.json :

tsc --init

It’s good to at list read that created tsconfig.json to see what options are available. For our project I will provide you this:

{
  "compilerOptions": {
    "target": "es5",                        
    "module": "commonjs",                   
    "lib": ["es6"],                             
    "jsx": "react",                   
    "declaration": true,                   
    "outDir": "./dist",                       
    "rootDir": "./src",                       
    "removeComments": true,               
    "strict": true,                          
    "noImplicitAny": true,              
    "strictNullChecks": true,
    "esModuleInterop": true             
  }
}

Most important for as are – "jsx": "react", "declaration": true, outDir": "./dist" and "rootDir": "./src"

declaration says that we want generate file with types

outDir – folder where we build files

rootDir – folder with source files

Third step – lets add some code

At the main folder we have to create our src folder

mkdir src

We need to install react and create or independent component

npm install react --save
npm install @types/react --save-dev

And create some simple component – standard one like counter in file src/index.tsx

import React, { useState } from 'react'

type CounterProps = {
  value: number,
}

export const Counter: React.FC<CounterProps> = ({ value }) => {

  const [counter, setCounter] = useState(0)

  const setCounterUp = () => setCounter(counter + value) 
  
  return (
    <div style={{ padding: 20 }}>
      {counter}
      <button onClick={setCounterUp} style={{ marginLeft: 15 }}>Like +{value}</button>
    </div>
  )
}

Now we can try to build our code:

tsc

In result we should have a new folder in project dist with index.js and index.d.ts

Now we are at the point that we want to verify our work. To do this we can always publish package, create new project and install this package there. That will cost a lot of effort and work. The best option is always to check our changes in fly – is it possible in this case? – Yes, but can be a little be tricky when you use react hooks. But we really want to do it! So let’s do it.

We can go an easy way – use create-react-app:

npx create-react-app example --typescript

Before we will use our package in example we need to add some stuff to package.json in main folder (main & types)

  "name": "react-component-wolesblog",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/react": "^16.9.3",
    "typescript": "^3.6.3"
  },
  "dependencies": {
    "react": "^16.9.0"
  }
}

Next step is to link our library

npm link
cd example
npm link react-component-wolesblog

Now we can modify example/src/App.tsx

import React from 'react';
import './App.css';

import { Counter } from 'react-component-wolesblog'

const App: React.FC = () => {
  return (
    <div className="App">
      <Counter value={1} />
    </div>
  );
}

export default App;

Save it and run in example folder

npm start

As a result we get:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

This is the headache point. Why? The reason is hard to debug but its coming from doubled react package. How we can fix this? We need to remove example/node_modules/react-component-wolesblog/node_modules/react

rm -fr example/node_modules/react-component-wolesblog/node_modules/react

Now we can try one more time start our example

cd example
npm start

As a result we should see working counter under http://localhost:3000/

Counter

Fourth step – add watch and reload

First we need to add some configuration to our tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                        
    "module": "commonjs",                   
    "lib": ["es6"],                             
    "jsx": "react",                   
    "declaration": true,                   
    "outDir": "./dist",                       
    "rootDir": "./src",                       
    "removeComments": true,               
    "strict": true,                          
    "noImplicitAny": true,              
    "strictNullChecks": true,
    "esModuleInterop": true      
  },
  "exclude": [
    "dist",
    "example"
  ]
}

As you can see we need to exclude dist and example. Now try command

tsc

That should build with success our package. Now we are ready for starting our continues development. In one terminal start example:

cd example
npm start

In second terminal type

tsc -w

On each change in main src folder tsc will rebuild package and example refresh automatically. Now you can start work on developing package far more efficient. When you will be ready you can just publish package with exported types just by. Don’t forget to update version in package.json !

npm publish

Now your package is ready to use in any other project from npm. Now anybody can type

npm install react-component-wolesblog --save

And use it as

import { Counter } from 'react-component-wolesblog'
...

In next part we will add some linting, tests and scripts to have a proper development boilerplate.

Next part here!

If this article was helpful for you – buy me a 🍺🍺🍺


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *