24
My experience in re-writing a simple library 3 times in 2 years
About four months ago, I posted this to document my ideas at the time to improve my one-and-only React package in a more developer friendly way.
This is a package I created to solve a problem of mine a while ago. Since the initial publish, I re-wrote the package three times. Every time I learned something new, I implemented my knowledge on the package.
First re-writing was after I learned JavaScript classes. So I tried to write the library using pure classes.
Then I learned TypeScript and re-wrote the package again in order to provide TypeScript support. This time I got rid of the class structure and made it more React-y.
Over the time, the users of the package gave some very valuable feedback. Even though I tried my best to respond to everything, there were some design flaws in the package that was bugging me.
So I wrote the post I shared earlier just to document my ideas. And recently got time to implement all of them.
React Step Builder used to provide methods for handling form state. If you had an input, checkbox, or select element, you could easily pass the methods provided by the library and it was saving it in a global state. The wrapper component was holding the state pieces from each step in a single location.
Handling state is a very delicate issue for a lot of React developers, including me. People use different solutions which they might not want to give up on.
The questions/concerns I got from developers consolidated the idea so I didn't want to force anyone to use those methods anymore. It was a simple step-by-step interface builder and I wanted to limit it's responsibility to that only.
In the latest version of React Step Builder, global state feature is completely removed from the library. So it's not a library that offers you some methods to handle your form state anymore. Think of it as a library to create any interface where user can go back and forth between different steps. That's it!
Before, the developer had to create their own Step components in a separate file and pass it as a prop to a special component called Step
. This approach has also proved itself to be very cumbersome. I even had trouble using the library in a project at work because of this.
So I researched more about React-y way of dealing with children
prop. Using React.Children
method, I was able to treat the direct siblings of the main wrapper component as steps.
I came up with this solution solely considering "Composition over Inheritance" principle of React. People should be able to create their component tree as they like and the library should do the rest. I realized I was creating more work for the developers than to save them time.
Now it's up to the developer to create their steps in the same component, or divide them up to separate files. This approach also made it easy for me to decide to halt global state management feature. Because when all the code for each step is in a single place, the state can live in the same place and be served to each step directly or via props, easily.
Removing Step
component brought about a problem that I really enjoyed solving.
Step
component was providing some useful props such as next
, prev
, jump
methods that are used to navigate between steps. Now I had to serve these methods in a different way.
Custom hook solution was my first choice as most React developers are already comfortable with the pattern. So I created a hook called useSteps
that provides all the properties and methods that were shared via Step
component's props before.
The component that holds the Steps
wrapper should be wrapped in StepsProvider
component for this to work and at first I didn't really like the idea of forcing the developers to use another wrapper component. However, being free from a special component's props and being able to use those methods anywhere under the provider's tree was the flexibility I wanted. So I went with the StepsProvider
solution where the data is shared through React's Context API.
I really enjoyed working with this library over the past two years. It's a novice-level piece of software but I learned so much through trying to develop this. It pushed me to research so many different things. Creating software for other developers is also very enlightening in a way that made me feel more responsible for the code I was writing. I kept asking myself, "would I enjoy writing code like this?" It's probably still not perfect, but it came a long way.
Please review the documentation, play with the codesandbox repo, use it in your projects, and let me know what you think!
24