React.js + Builder: A game-changing combination
Published: 2024-04-21 16:52:00

Today we're going to talk about a well-known design pattern, Builder, which in itself is already very versatile and powerful, but we're going to combine it with one of the best-known front-end frameworks at the moment, React.js. I'll show you how to work with components that are constantly repeated in a different way than what React.js already proposes. Imagine creating a complete form using just one line of code? This is what Builder will provide us.

## What is Builder?

It is a software design pattern used to create complex objects step by step. It is useful when constructing an object requires many steps or when we want to create objects that share similar characteristics but may have different configurations.

Think of the builder as being like Lego. With Lego you can build various things, such as Harry Potter's castle, the Millennium Falcon from Star Wars, Thanos' Infinity Gauntlet, among many others, that is, they have similar characteristics of being Lego, but with different configurations. Builder has the same idea, but instead of Lego pieces, we have pieces of code that can be combined, in our case we will have React.js components, which will be combined in any order.

## Let's code

What we will use: Node.js, React.js, Typescript and Mui Material (Optional, I will only use it to facilitate the creation of form inputs).

First let's start by creating our interface, which our component classes will need to follow:

![InputForm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzr6kfubltsqg73lnv33.png)

Note that I will be using ReactNode typing, as each “piece” of our builder will contain a React component.

Now we need to create our Builder class, which in this case I will call FormBuilder, as we will use it to build forms.


![FormBuilder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kvydiqetnejgeoto1gm.png)

Note some points in this class, its constructor is private, as it will not be instantiated outside of itself. Still in the constructor we receive an array of interface components that we created, because in the end the Builder returns this, an array of react elements. In the class methods, we have init, which must always be called at the beginning, as it instantiates the class and starts with an empty array. We also have build, the method that must always be called at the end to finish the Builder and return the list of components.

Next, we can build our React components, in this case, I'll start by creating a simple Checkbox, using Mui Material:


![Checkbox component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vf3mgxzw58qcyuow3q7f.png)

With the component ready, we need to create the class for this checkbox:

![Checkbox class](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgs4n10qt1uva2qsa2jj.png)

Here is one of the secrets of this development, we will create a class like this for each new component, in it we have the component property that must receive a ReactNode component. If we analyze what a React component is, it is nothing more than a function that returns an element of type ReactNode, when used in other tsx files we call it <CheckbocComponent/>, however in this ts file we can treat it just as a function normal that returns a ReactNode object.

With these two files ready we can add them to our FormBuilder.ts:

![Form builder with Checkbox](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83ck9d63iqr7y15uhful.png)

This is the point that makes the builder work. When adding the checkbox, we create a new checkbox method, which will instantiate the previously created Checkbox class and insert it into the InputForm component array. When the method returns, we return the instance of the FormBuilder class itself, so that it allows us to add other methods in a concatenated way.

Now our Builder is ready, but it is a bit poor, with just one component, so repeating the same checkbox process I created 3 more components, InputDefault, DropdownInput and Switch.

![Complete form builder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fksm9hcux3y6fyy3v1i4.png)

We finally have our Builder complete with several components, time to put it to work. Just create a new one-page React file and add the following code:

![Complete page 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4b3rgscc7013mziwu584.png)

Then we have a result like this:

![Full form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/me7cjucvw57k5850kvg5.png)

##Let's level up this code

The time has come to go further in the use of Builder, imagine the following challenge, you work in a company that sells various types of courses, and at each start of the course it is necessary to have a form that provides information to the student, and this information varies according to the need for each course, that is, we need a different form in each case. The form configuration should work as follows, on a dashboard the company employee configures the inputs he wants in the form, once completed, all this configuration must be saved in the format of an object in MongoDB, and at the beginning of the course if queries this object in the database and creates the form from it.

This is an extremely challenging scenario, and it was a situation like this that I experienced working as a developer. The people on my team had already made a v1 for this case, but it constantly had problems and had huge code, so that's when I had the idea of making a v2 using the Builder that was built at run time, just by reading the object in the database and adding the necessary input.

In this second part I will show how to configure the builder for this scenario.

##Let's code (again)

With the previous code done, we can start by adding, in the same file where the InputForm interface is located, a new enum and a new type:

![Properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlg9aypbbpmfj2cruvqa.png)

Our new type Property will be crucial, as its first type property with the typing being the enum COMPONENT_TYPE determines which input will be used, it is crucial that the value of the enum elements are the same as the names of the methods created in the Builder. Its other property, props, is typed with the props of each component we build, as it must have information about each property used.

Now we just need to create our DynamicFormBuilder class:

![Dynamic form builder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydzb7vvkt5815z3vwxvb.png)

This class has a method called execute that is prepared to receive an array of Properties, which we called Properties in the previous file. With this array in hand we can traverse it, and this is where the Property type is important, as it references each Builder method.

Now it's ready, just add this class to a React component and just by passing an array of objects we can create any form the way we want:

![Dynamic form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jn68uvnjlvgzr7quzah8.png)

In this gif I show how the result turned out, where on one side I placed some fields to choose the input to be added and on the other side the form was created automatically:

![Gif](https://git-articles.s3.amazonaws.com/CPT2404191926-1465x916+(1).gif)

If you want, you can also see the code on my GitHub: https://github.com/igormattiolli/react-builder