Here at Yeti we love learning new things, so twice a month we open up the floor to presentations on areas of personal expertise. Topics range from the basics of inbound marketing, to design for startups, to tips for living and working out of a backpack! Our awesome developer, Resdan, recently gave this presentation on creating a reusable component library. Enjoy the video!
So I'm a front-end developer here at Yeti. And I've been working on creating a reusable component library.
The problem that I was seeing is that each project requires similar components created over and over. We iterate the projects very quickly. We tend to make a lot of components to satisfy those project solutions. And there should be some way for us to cut down on the amount of time that we use towards making those same components over and over.
Another problem that I was interested in tackling was that complex components are created and forgotten. There are specific components that we create for specific projects. And although they might be project specific, the pieces and the logic behind those components could possibly be reused. Or even better if we find a way to create a more reusable option on that component, we can then reuse it if we see fit in another project without having to reinvent the wheel of creating that component again.
Another problem is similar components have different props. So there could be one front-end developer here at Yeti that creates a button that takes in three props; could be error, text, and say size. Then another developer might make a same button on another project and it only takes in text and height. I was trying to see if we could streamline the props that we all use in all of our components across all of our projects.
So the solution was to create a single place for all of your reusable components that always have the same props. Another thing to add to that is that you would want to document your components so that anyone that sees where these components are being made from can easily determine what props that component uses and what its function is.
Research and development. So this is how I got started. It was pretty much a three step process. The underlying layer of it, step one at the button, was just… I found it a very lightweight easier solution that contained all of the necessary dependencies that I needed to get a project up and running very quickly to publish to NPM. I included a link to that. It also included TypeScripts so that was right out of the box. Very easy for me to implement. Not a lot of pain on my part.
The second step of that was creating reusable components across targets. There is a github repository called React Primitives. It looks to bridge the gap between React Web and React Native. So that you create a component in one place and you can use it on both targets which is really helpful being able to create a component library.
The third step was documenting the components props and function, which I did inside of yeti/redline. That’s where I decided to call the project. These three steps led to me creating a component library that was easy to understand, easy to implement, and very easy to build upon. I was very excited that I found all this information and it created a very easy solution for something that I thought would be a lot more complex in theory.
So this is an example of a component using those three steps. It’s just something called a profile image. I don’t know how big that is. Actually, that’s pretty good. Hopefully, you can see some of the code there. I’m just going to talk about a few things really quickly. I imported the image component from React Primitives like I mentioned earlier. It’s a low memory solution. It hits web and native targets. I also used TypeScript right there on line 5. Then you’re going to export to the props. It’s only got two props. So very low amount of props and easy to understand. It just takes a URI and a size. And it actually just computes the width and the height from size and has border radius of half the size, making it basically a circle product without having to add an extra prop of border radius.
The image just expands to fit the entire width and height of the container that it’s contained in. And it also has default props. So another thing that I wanted to make sure was that if you like bring in a reusable component, I don’t want it to cause an error without you bringing in any props. So even if you place it somewhere, you at least can continue coding the rest of your app or project without it completely breaking, and you not understanding where that break or error is coming from. So very simplified profile image which is really easy to understand props and being able to be built across several targets.
So documenting this component. Actually, also very easy. I just added it to the README. I know it’s a little blurry down at the bottom. I just wanted to show the entire README so you could see how simple and easy it was to add items to the components. It also outlines the component props. It includes the name and default props for easy understanding. So again I don’t want anybody to be confused about what they’re trying to import when it comes to the profile image. You know that even if you import the profile image with no props at all, it will still work without erring or breaking your code. It will show an image which is what its designed to do regardless of whether you put one in or not. But it does want a specific type for each prop. And an example is shown in the README of what that prop should look like.
So another part is publishing to NPM. That was a little bit more difficult at first because of the nature of how universal I wanted this component library to be. So the simplest steps to get this through is just to make sure that your code is error free, determining dev and peer dependencies, and pushing changes. That middle one - determining dev and peer dependencies – was the most difficult part of the process because I need to make sure that I only include in the package the correct dependencies, development-wise, so that when you install it for your project you are able to only install the peer dependencies that you need to get it to run on the targets that you’re looking to shoot for. That sounds a little confusing but in practice it’s a little clear. And fortunately, the difference between dev and peer dependencies make the NPM package very easy to understand when you’re installing.
So an example use case of this is you see here that there is a computer, a laptop, an iPad, and a phone. And some of these components are very reusable and almost identical. The text, an example for that would be like Font and Size Styling depending on target. Clearly you don’t want your text to look the same for the header on a website as you do for a phone, but you still have a component that takes in a string and displays text based on where the target is.
Another one is buttons which includes possible redux functionality and error handling. And there’s a button down there at the bottom. And that button could be reused across all the projects depending on the size and the width, and then whatever you want to do when it comes to error handling. And the next part of the app that you want the button to guide the user to.
And then there’s also forms. So that entire component there has inputs and texts and the button. And if you wanted all of that to be useful and reusable across all these projects, you might be able to use a component library to do that.
So these are some of the benefits of creating a component library. It’s easy to use, it’s increased productivity, and increased code reuse. That previous example; if you only have to create a form once, and you use it for web and your iPad and your phone, then you eliminate the need to have to create it three times across all the targets.