How I fell in love with React (Part 4): Sharing Worldwide
This is the fifth chapter of a series of articles called “How I fell in love with React” where I will share with you everything I have learnt and done in my first month using React (from August 15th to September 15th, 2016).
You can find past chapters here:
After my first two “projects” I was hungry of more challenges. I definitely didn’t know what to do next, but I decided that whatever I would do should be useful for future projects.
I ended up choosing a carousel-like menu navigation that many applications use. Funnily, I realized later that Youtube mobile application (which I use almost everyday) has that exact system.
Back in the second chapter of the series, I said that in my opinion one of the most fascinating thing about React is the possibility to share your Components through npm (it is not React exclusive thought, all the JS ecosystem benefits from it).
So I decided additionally that I would share the component on npm, which is a little bit more trickier than expected.
To summarize, I wanted to do:
- A menu with 4 buttons and a content zone.
- Whenever the user presses one button the content changes to correlate the button pressed.
- You can also navigate from one content page to another by swiping.
- Swiping because I wanted a mobile first design.
- The content zone must do a smooth moving transition while changing.
- Finally it has to be customizable by users who download it trough npm.
Research phase
Everytime I start doing something I first search if something similar have already been done. You would be surprised how many times you can find exactly what you were starting to do.
This time however, I wanted to think a little bit about the problem before searching the solution. So I started with the most basic thing: a static HTML mock-up of what I wanted to do.
Next I had to figure out was how to detect swipe on mobile.
My first approach was:
- Start interaction, record (X, Y) initial position.
- Whenever it ends, record final position and calculate difference.
But I didn’t know how to write that in JavaScript. RIP.
After several Stack Overflow questions [thank you Stack Overflow], I found out that there is a library called Swipe.js that does most of the job for you when creating a touch slider, you don’t need to write the code from scratch like I wanted to do.
I felt very lucky, the library handles swipe detection plus the logic of touch slider for my content. However I didn’t know how to use it within my Component and how to make it affects the content…
That was the moment where I took a breath and thought “Okay, I have tried, but I don’t have the knowledge yet. Let’s search if someone did something similar using React”.
Indeed there was already a carousel-like component for React. And guess what ? It was using Swipe.js
Building Phase
I tried the Component and it was working nicely. Now I just needed to add on top of it the menu buttons and…yes, just switch content when one of them is pressed.
Easy to say, but hard to do.
There was also an addittional problem: when you swipe you are going to current-index to +1 or -1, but with buttons I needed a way to go from 1 to 4 or 3 to 1.
So I dived into the library code and took a look at the React Component to know how it was importing the Swipe.js functions. Then I searched in the Swipe.js source what other functions where available to import (there was indeed a function goto(index )).
It took me a long time to understand some JavaScript concepts that I didn’t have but it ended up working.
One key part was to know how to call from my Component class the functions imported in the carousel-like Component (which was importing them from Swipe.js). I did it by saving the carousel instance with ref attribute and later calling directly the function on that instance.
// First
<ReactSwipe ref={(c) => this._panels = c} ..... </ReactSwipe>// Then
this._panels.slide(index);
Sharing phase
Then I thought: “Not everybody will want a 4 item menu with exact pages called [Home, Blog, About, Contact]”.
So I modified the component to take an array of names as prop and use them instead the pages name I set. Also you can set more than 4 pages adding more elements to the array.
Finally I made easy to tune minimum swipe differences values and the speed of transitions between pages.
If you want to know how all this abstractions were done, check the source code and feel free to ask me anything :)
Note: in general abstracting Components to override hardcoded configurations is a tough job (except for these kind of small Components). The great thing about doing it is that they will be ready to be used in very different scenarios.
It is generally commended to always abstract Components to make more agile developments, but if you are working on a personal project and abstracting a Component would take you a lot of time for no clear benefit, I would recommend just not abstracting it.
npm Phase
In last place, I had to upload it to npm. I followed the official documentation and “successfully” filled my package.json file with some extra values (like description, keywords or license).
I had a cool package.json with all the information possible about my packgage but…
There were two things to do in webpack.config.js needed for React Component publishing. I struggled for days to find them.
1) You need to define values for library and library target:
......output: {
library: 'ReactSwipeNavigation',
libraryTarget: 'umd',
...
},......
First property is the name you want to give to your component’s library and the second one must be umd which stand for “Universal Module Definition”.
2) A little bit more obvious, but I did the mistake to bundle my main.js file over the Component itself.
That means I was serving the code of a instance of my component, and not the component itself.
To fix it you need to set in your webpack.config.js file your Component’s file as the input file. In our environment setup, that means to put App.js as the input file.
How to test it
At first I didn’t know how to test my packages without uploading them to npm, which was a longer process and would make me publish tons of versions before getting it to work.
I eventually arrived to the idea that you can use the bundle as it was any other of your .js files. That means import it like we do in main.js:
import MyComponentName from './MyBundleFileName';
Of course if you have props that affect Component’s rendering you should see easily if it is working. In my case I tried replacing the name of one the menu buttons.
Final considerations
PropTypes
It is a good practice to define prop types expected, that way both you and people using your components know when they are passing incorrect types.
A basic example would be:
MyClassName.propTypes = {
initialValue: PropTypes.number
}
That way we are saying that we expect a prop called “initialValue” which is a number.
DefaultValues
Also, you can define default prop values. That way, if a prop is not passed, its default value will be used.
For example the speed of transition in our component is by default 300. Most people won’t even need to tweak it, so they can avoid specifying it.
// Defining
ReactSwipeNavigation.defaultProps = {
menu: [ 'Home', 'Blog', 'About','Contact'],
// thresholds for valid swipe
minX: 5,
maxY: 50,
speed: 300
}// You can later just use
<ReactSwipeNavigation>
....
</ReactSwipeNavigation>
// And the values from above will be used-----------------------------------------------------// This would override the menu array default value
<ReactSwipeNavigation menu={['Best', 'Menu', 'Ever']}>
....
</ReactSwipeNavigation>
README.md
Whenever you publish something on npm you should try doing an amazing README file explaining what is your Component, why it is cool, how it can be used (giving some examples), how you can customize it (if there are posibilities) and…basically everything you consider important for someone that doesn’t want to deep into your code but want a fast solution to their need.
To do so, I first looked at popular Components’s READMEs and tried to imitate how they “present themself”.
You can take a look at the README I did for this Component. It is pretty simple but very self explanatory.
TIP: If you add a GIF and an online demo you will seem a pro !
That’s all for this chapter ! Let me know if this has helped you by clicking the heart icon button or sharing it on social medias :)
In general, I am pretty sure that I was over killing a lot of things, but it was just my solution to a given challenge with a restricted set of knowledge. It was not about doing it perfectly but just doing it. I will probably come back to the source code in a few months and improve it.
The Component actually sits on 926 downloads.
You can check the Component Github page for more information !
Have you already shared a React component? You should !
It is a lot of fun and you could potentially be helping tons of people !
Let me know in the comments below if you faced any other kind of problem !
Have a nice day
Giveaway: if you have reached the end and you want to learn what is Redux you should check this fantastic free course by Dan Abramov.
EDIT:
Author
Enzo Ferey, developer and ReactJS lover
Eating, always eating.
www.enzoferey.com