Building a Dynamic Form in React (Part 2)

A devlog of my first experience using React to create a dynamic data-driven web form, and learning the ropes of components, forms, Fetch and everything in between.

Last week, I talked about the work I started on a dynamic React form. A lot of progress was made since the build I showed and those changes and additions are the focus of this post.


In the last build, validation was based exclusively on the publish/unpublish dates of the repeater. The latest build includes a complete filter for most repeater form fields (though content type and name aren’t implemented).

This necessitated the creation of a new component that could handle its own input state. I could have done it via Formik, but I found that writing my own forms wasn’t difficult, so I did it in vanilla React. I did not wrap the inputs within a form element, so as to avoid having two forms on the same page and make it clearer from a coding point-of-view that the component is not a standalone form processor – it only passes a JSON to the main App component when the submit button is hit.

Once the filter values are submitted, the App component uses them with my new filter method. This just reads the JSON that was stored in the component’s state and returns either a disable class or a ks_repeater class, depending on whether I want to show or hide the repeater.

Right now, the repeaters are shown under two headings – “Active” and “Inactive” – according to whether they are valid or invalid under the filter. In the future, rather than setting display: none, as is currently done, I will keep the repeaters visible under the same header but with styling to visually communicate whether it’s filtered or not, as well as display the current filter options.

As well as implement the option to search by repeater name, I will remove a few fields like play length to streamline the interface.

Contextual Fields

I extended the logic of the disable switch to limit the repeater to display on the fields that are currently relevant to the user, after they have filled out parts of the repeater in a logical order. On each render, a wrapper around each field/label (in actuality a separate component designed to reuse identical code) checks if certain conditions are met in the user flow – like if there’s a content URL or a play length – and displays the next field(s) if the condition returns true.

This has the effect of improving the usability of the app by restricting the on-screen fields to only those the user needs to interact with at any given time. The current implementation will be streamlined even further, by hiding additional fields behind a checkbox to enable more options – by default, the scheduler will assume that repeaters play 24/7.

Live Preview

A very rough version of a live preview is currently implemented in the latest build. It displays some unreliable behavior, but the idea is to show a live preview of the content URL inside an iframe. A button on each repeater calls a function to replace the iframe src attribute with the value of that repeater’s content url input.

In the future, once the bugs are worked out, the live preview will be displayed as lightbox popup instead of being mounted on the side of screen at all times.


The main drawback to the latest update is performance. The performance in the previous build was acceptable – it ran well within 15 or so repeaters. The latest build shows drastic decreases in performance within 4 repeaters. I am still investigating the cause, but I have a few options I can think of:

  • Find the problem code and optimize it
  • Ask for help optimizing Formik forms
  • Replace Formik with a custom solution

Fixing the problem myself would be ideal, followed by finding someone who has encountered this issue before and knows how to fix it.

I’d rather not have to hand-code a new form handler for the scheduler, if only because Formik does a good job handling my dynamic form inputs. However, it is not beyond my comfort zone or ability to do it, so it’s still a viable last resort, and would at least prove rewarding to do. But, for the sake of efficiency, I’ll try to fix the problem without adding more work than necessary.

Next Steps

The next step is to fix the performance issues, because if I need to write a new form handler, I’d like to do that ASAP.

The client has also asked that the JSON output be reformatted and that I add another field for a future version of the slider software, which is an easy task. He also wants the ability to select the loaded scheduler, which will be a fun exercise, but one that I believe is well within my capabilities.

It will require reworking the initialization of the app and adding additional functions to the PHP filesystem, as thus:

  1. Load app
  2. App calls PHP with a query to fetch available schedules, then
  3. PHP fetches schedules and posts schedule names, then
  4. App renders schedule selection interface
  5. User selects schedule
  6. App calls PHP with request for specific JSON
  7. The app runs as it is now

At least, that’s the hope. AJAX is something I don’t use a lot yet, so there may be something that trips me up. Whatever happens, I’m confident that my next blog post will come complete with a schedule selector.

And then I can work on the UI!

Finally, here’s the latest build.

More to Explore

Unity State Machine Boilerplate Code

The following boilerplate code is for a basic finite state machine implementation in Unity, written for my own reuse with comments provided on usage. It

Building a Dynamic Form in React (Part 1)

A devlog of my first experience using React to create a dynamic data-driven web form, and learning the ropes of components, forms, Fetch and everything in between.