Are you looking for a kick-start to guide you through the process of building a reusable React component?. Are you also wondering how to integrate the Flux Architecture Pattern and be able to publish your work as a public npm module?. If your answer is yes, or you’re just curious about what I’m talking about, this post is just for you.
Table of contents
- Preparing things up
- Start coding
- Publishing to npm
- End of tutorial
What are we building ?
Through out this tutorial we’ll get our hands on coding to create a simple React component, that will consist on a list where you can add, edit, remove and search items. Flux will be the pattern followed to manipulate the list state.
We also want to publish our component as a reusable module, and here is where npm comes into play, and we’ll be using it from the beginning to also manage our dependencies.
So, here’s a summary of the tools we’ll be working with throughout the development process:
What should you have experience with ?
This tutorial is not intended to be an in-depth guide on how to use any of the tools/patterns mentioned before. Quite the opposite, this is just a simple kick-start to guide you in the right direction so you can further develop your skills.
No details about version control with Git will be given throughout the tutorial.
In a hurry ?
If you’d like to just go and take a look at the final source code, check it out here.
Preparing things up
Initialize a Git repo
Create your project folder, we will be referencing it as
react-list/ throughout this tutorial. Initialize it as a Git repository and set its remote.
Initialize with npm
Run the following command in your project root folder (
This will prompt you to enter the following information:
- Module name. Make sure that it doesn’t exist already in the npm registry, or just scope it with your username: @username/module_name.
- Module SemVer version number, it will default to 1.0.0. We’ll take care of this later.
- Simply describes what your module is/does. Could be something like React Component for a list where you can add, edit, remove and search items., in this case.
- entry point:
- This is the file that will be included when someone requires your module. It will default to index.js. We’ll take care of this later.
- test command:
- The command that will be used for running tests. We won’t be developing tests, so leave blank.
- git repository:
- Your remote Git repo. If you’ve already set a remote, it will default to that one.
- This lets people discover your package. Could be something like list, items, react, react-component, in this case.
- Your name.
- Just to let people know what license you’re using. Let’s go with MIT (remember to include the license in your source code).
After you answer to all of the past prompts, the resulting
react-list/package.json will be outputted, asking for your confirmation. If it is OK, just answer yes and we’re done with this step.
Add some structure
Too keep things simple, let’s just create the folder
react-list/src/ where all our source code will be present (in an organized manner). Also create the file
react-list/src/index.js, that will serve as our entry point for webpack.
First of all, we need to add webpack as a development dependency for our module. This is simply done running the following command:
npm install webpack webpack-dev-server –save-dev
npm install babel-core babel-loader babel-preset-es2015 babel-preset-react –save-dev
Now we can create our webpack configuration file:
Let’s give a simple explanation for each one of this configuration options:
- The directory where webpack will look for the entry file.
- The entry file that webpack will use for bundling.
- library: This needs to be specified for bundles that’ll be used as modules/libraries. It’s just a name for the library.
- libraryTarget: This is the kind of output for the library, here we specify commonjs2 because we’re offering it as a module that needs to be imported.
- The path where the bundle will be saved.
- The bundle file name.
- The file extensions that webpack will use for bundling.
- Specify dependencies that are not resolved by webpack.
Add the following script to
react-list/package.json, so we can use it to build our bundle:
Now we can run the following command:
npm run build
We should have our first bundle built on
react-list/dist/react-list.js (of course with no functionality yet).
As said before, our module will consist in a React component, this means that it will be used as a plugin from an enclosing React project. Given this, we won’t add React as a direct dependency for our module, instead it will be a development dependency, but we must also specify it as a peer dependency inside our
So, first of all let’s add React as a development dependency for our module:
npm install react react-dom –save-dev
After that, we add the following to our
I encourage you to read a bit more about peer dependencies here.
Alt.JS and Immutable.JS
npm install alt immutable –save
We’ve finally arrived to the fun part of the tutorial: coding.
Now we can start building the flux store that will hold our list state:
This creates a simple store that holds a list of items initialized with some dummy values.
With our store ready, we can create the main React component that will listen to changes in the store state:
It’s worth noting that here we’re using an
AltContainer component, that’s offered by Alt.JS as a helper to make it easy to listen to a given store state and pass it down as props. Read more about
In the previously shown code, we imported a
List component, that will take care of rendering our list:
Webpack entry file
With the previous defined files, we have simple functionality developed, but we haven’t updated our webpack entry file to export our main component
react-list/src/components/ListContainer.jsx. Let’s do that right now:
Now we’re ready to see our premature module in action. To do this, let’s create an alternate webpack configuration file for development, that will be an exact copy of the original one, with exceptions in the
This defines a different entry file to be used, and it also specifies a path (
output.publicPath) that must be used to reference the bundle from a public directory on a local server.
Then, we create our entry file for development:
This will try to render our main component into an HTML tag with the main id, so let’s create a public directory, with an HTML file that we will serve through webpack-dev-server:
Everything’s set to lift a development server, and see our module in action. Add the following npm script:
npm run serve
Open a browser, and go to http:/localhost:8080/. Our simple list should display.
Setting initial list items via props
We want to be able to specify initial items for our list. This can be done through props in our main component. But first, we need a flux action that will permit us to update our store items:
Actions in Alt.JS are just functions that receive an arbitrary number of parameters, and must finally call the Flux Dispatcher with just one parameter. Here we’re declaring an action that will receive a list of items and dispatch them.
Now we need to bind the previously specified action to our store:
An action handler inside a store, must be a funcion that should receive the parameter dispatched. Here we’re receiving the list of items dispatched, and initializing our store items from that list.
We still need to update our main component, to be able to receive a prop with the initial items, and update the store accordingly:
Notice how we’re forcing our items to be objects with a
name property. This is to keep things simple, but this can obviously be modified to represent a more complex item.
Adding list items
One of the features we want for our list, is to be able to add new items. This will be done through a simple text input (as said before, to keep things simple and just have items with a
name property). Following the same flow as before, let’s create our action first, that will receive an item and dispatch it:
Now we can bind this action to our store, that will receive the dispatched item and add it to the list of items:
With this ready, we can update our React components accordingly.
Let’s create a
NewItem component that will hold a simple form to add new items, and handle its submission:
It’s worth noting how we are exposing a prop to specify a callback that will be executed after a new item is added to the list, with the recently added item passed as a parameter. This has the purpose to enable custom behavior (persist data into a back-end for example).
Now let’s update our
List and main components accordingly:
Removing list items
We’ve already developed the functionality to add items. Now we want to be able to remove items from the list. Simple: create the action, bind to store, and update components accordingly.
The action will receive a list index and dispatch it.
The store will receive the dispatched index and remove the corresponding item.
We need an
Item component, that will represent each one of the items in the list, and it’ll offer functionality to remove the item:
The props defined include the item itself, its index, and an exposed callback that will be executed on item removal, passing the index and its corresponding item as parameters.
As before, we need to update our
List and main components:
Editing list items
You’re getting used to this right?, then let’s get right to the code.
The action will receive the index and the new item, then dispatch this data as an object (remember that the Flux Dispatcher can only handle a single parameter).
The store will receive the dispatched object and modify the corresponding item in the list.
We don’t need to develop a new component, but we must modify the existing ones accordingly to offer edition functionality.
Notice again, how we are exposing a prop for a callback to be executed each time an item is edited. The callback will receive the index edited, the original item, and the new item.
Searching items on the list
We’ve already developed 3 out of 4 proposed features for our list of items. The final feature we’re going to develop, is filtering the list by a search query (text). The matching items will be those that start with the given query. Let’s get coding.
The action will receive the query text and dispatch it.
The store will receive the query dispatched, and filter the list correspondingly.
It’s important to keep an original list, so we can search items without losing information. That’s why we are adding an
auxItems property to our store state.
We must create a
SearchBox component, that will serve as a simple form to enter the search query, and filter the list as the query changes:
As done with the other features, we’re exposing a callback to be executed each time the query changes, passing the query as a parameter.
That’s it, we’re done developing the proposed features for our list. Everything’s pretty simple of course, if you’re already wondering how to improve this reusable React component (I do have a lot of ideas in mind), don’t hesitate and go ahead and improve it, you can always contribute to my module here (the latest version may be way advanced from what we’ve developed here, the tag corresponding to this tutorial is 0.1.0).
We still need one more thing to care about according to this tutorial scope: npm publishing.
Publishing to npm
Creating a user
If you don’t have a user on the npm registry, you should add one by running the following command:
This will prompt you for a username, password and email.
If you created one on the npm site, use:
This will prompt for your credentials.
We should update our
I’ve decided to change the version number from 1.0.0 to 0.1.0 because our module is pretty simple and naive yet, not really qualifying as a major first version.
main value is referencing the bundle generated with webpack, which is what we really want to expose.
We don’t want npm to keep track of source/development files on our codebase, so let’s create the following file:
node_modules public src .eslintrc .gitignore webpack.config.dev.js webpack.config.js
Build and publish
Before publishing to npm we need to make sure that we build our bundle:
npm run build
Now we can publish:
npm publish –access=public
--access=public flag only if you’ve scoped the name of your module. This is because scoped modules are private by default, and you’ll need an npm paid account for that.
End of tutorial
I really hope you found this useful to improve your skills, or at least have a general idea about the techs/concepts we used/discussed throughout the tutorial.
What next ?
About the module we built, there are lots of features/improvements that can be done, try the following:
- Permit arbitrary objects as list items, and expose a prop to specify a renderer that could be a function that receives an item and returns the content to render.
- Add CSS classes to each relevant element inside components, so it is easy to customize the general style for the list.
- Be creative.
I also encourage you to further read about he following topics/techs/tools: