Creating my first React Package - React-unicons
Tags: react, javascript, icons, package
Published: 2019-07-20 12:40:11

---
title: Creating my first React Package - React-unicons
published: true
description: React-unicons are 1000+ vector component based icons for React.
tags: react, javascript, icons, package
---

Hi guys,

Since long I wanted to work on and create package in React. I am mostly working in VueJS, thus this was a bit new experience for me.

Recently, we launched [Unicons - an icon library](https://iconscout.com/unicons) containing 1000+ vector icons in unique line style as open source. And since then I wished to have package for React. Last Sunday, I was kinda free & thought to give it a try! And here I am writing this article.

## How to
There were few ideas in my mind related to how I want to make it available. Some of them contains:
1. Easy to use for everyone.
2. Component based
3. One should be able to load only icons that they need, keeping bundle size as low as possible.

I wrote a script that converts the SVGs to React components. I used folder based approach like `lodash` to keep the bundle size smaller. Every component gets compiled into different React component file and gets imported to common `index.js` for those who want to use all the icons.

Here is a sample component of `comment` icon:
```js
import React from 'react';
import PropTypes from 'prop-types';

const UilComment = (props) => {
  const { color, size, ...otherProps } = props
  return React.createElement('svg', {
    xmlns: 'http://www.w3.org/2000/svg',
    width: size,
    height: size,
    viewBox: '0 0 24 24',
    fill: color,
    ...otherProps
  }, React.createElement('path', {
    d: 'M12,2A10,10,0,0,0,2,12a9.89,9.89,0,0,0,2.26,6.33l-2,2a1,1,0,0,0-.21,1.09A1,1,0,0,0,3,22h9A10,10,0,0,0,12,2Zm0,18H5.41l.93-.93a1,1,0,0,0,0-1.41A8,8,0,1,1,12,20Z'
  }));
};

UilComment.propTypes = {
  color: PropTypes.string,
  size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};

UilComment.defaultProps = {
  color: 'currentColor',
  size: '24',
};

export default UilComment;
```

The build script that I wrote looks something like this:
```js
const path = require('path')
const fs = require('fs-plus')
const cheerio = require('cheerio')
const upperCamelCase = require('uppercamelcase')

const iconsComponentPath = path.join(process.cwd(), 'icons')
const iconsIndexPath = path.join(process.cwd(), 'index.js')
const uniconsConfig = require('@iconscout/unicons/icons.json')

// Clear Directories
fs.removeSync(iconsComponentPath)
fs.mkdirSync(iconsComponentPath)

const indexJs = []

uniconsConfig.forEach(icon => {
  const baseName = `uil-${icon.name}`
  const location = path.join(iconsComponentPath, `${baseName}.js`)
  const name = upperCamelCase(baseName)
  const svgFile = fs.readFileSync(path.resolve('node_modules/@iconscout/unicons', icon.svg), 'utf-8')

  let data = svgFile.replace(/<svg[^>]+>/gi, '').replace(/<\/svg>/gi, '')
  // Get Path Content from SVG
  const $ = cheerio.load(data, {
    xmlMode: true
  })
  const svgPath = $('path').attr('d')

  const template = `import React from 'react';
import PropTypes from 'prop-types';
const ${name} = (props) => {
  const { color, size, ...otherProps } = props
  return React.createElement('svg', {
    xmlns: 'http://www.w3.org/2000/svg',
    width: size,
    height: size,
    viewBox: '0 0 24 24',
    fill: color,
    ...otherProps
  }, React.createElement('path', {
    d: '${svgPath}'
  }));
};
${name}.propTypes = {
  color: PropTypes.string,
  size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
${name}.defaultProps = {
  color: 'currentColor',
  size: '24',
};
export default ${name};`

  fs.writeFileSync(location, template, 'utf-8')

  // Add it to index.js
  indexJs.push(`export { default as ${name} } from './icons/${baseName}'`)
})

fs.writeFileSync(iconsIndexPath, indexJs.join('\n'), 'utf-8')

console.log(`Generated ${uniconsConfig.length} icon components.`)
```

Earlier I tried to use `webpack` and it didn't work out properly as it compiled them into single `index.js` file.

## Publishing it as npm package
I learned how to publish it as a npm package so that everyone can use it via simple `npm install`. I've published it at https://www.npmjs.com/package/@iconscout/react-unicons

## Use
You can use these icon by simple installing
`npm i -s @iconscout/react-unicons`

and then import individual icons in your component.
```js
import React from 'react';
import UilReact from '@iconscout/react-unicons/icons/uil-react'
 
const App = () => {
  return <UilReact size="140" color="#61DAFB" />
};
 
export default App;
```

I have also added props to customise color and size.

I would love to have suggestions from DEV.to community on how I can improve it. :)