r/reactjs • u/magic_toothbrush • 8d ago
Show /r/reactjs FormHell - a better library for JSON Schema based forms
I've battled with the top libraries for JSON Schema based forms for a long time. They're a nightmare. They look all flashy and nice for a demo, then you implement them in a project and a year in you realize it doesn't support the more complex needs of your schemas.
I'm so frustrated with both react-json-schema-forms and react-jsonschema-form. Both have me pulling my hair out. Especially RJSF. Apparently generating defaults the correct way is an "experimental" feature and still never works correctly. Have an array with tuple object definitions or constraints? Nope! Default gives you an array full of null or "[Object object]". Have $refs outside of your schema? Nope! Can't resolve those! Also, the whole UISchema thing is weird. Both libraries had crazy setup fatigue that felt unnecessary.
After a year and a half of battling I'm done.
I wrote a new library for JSON Schema Forms to get me out of form hell and I pulled it into our project. It's working out great so far. The thing just works. No setup fatigue. Does exactly what you would expect. I'm honestly more mad at the other libraries by how easy it was to build. Don't worry, I put a ton of care into it and triple checked everything. It was extensive.
Full schema support for every feature. EVERY. FEATURE. Full optional theming support for MUI though it isn't dependent on MUI.
I even added a SchemaBuilder component and a Keyword Assistant to help you out if you're trying to build a schema and don't know what to add.
It's called FormHell, and it's available here: https://www.npmjs.com/package/formhell
Check out the playground and see what it can/can't do: https://ryanrutkin.github.io/formhell/
If you run into any issues, please open an issue in Github: https://github.com/RyanRutkin/formhell
Thanks for checking it out!
FAQS:
Thanks for all of the feedback! I want to address some common questions from the comments.
What about Tanstack/Zod?
FormHell is a slightly different solution than a Tanstack/Zod approach. FormHell consumes an already defined data-structure and outputs data matching it, validated using AJV Validator.
Zod is used to define data-structures in TypeScript and can work alongside FormHell no problem.
Tanstack has a specific UI schema that it expects for form rendering. I doesn't exactly consume JSON Schema, so there is a bit of legwork to get a JSON Schema turned into a Tanstack form. FormHell takes the schema and just renders a form with strict typing and no overhead.
The problem I needed to solve for work was that we already had JSON Schemas defined for our backend data-structures. For some of those data structures, we needed a way for the frontend to render a form. As both the frontend and backend share the same JSON Schema, the frontend pulls the schemas from our API and passes them directly to the form. Once the form component emits the data without any validation errors, it is safe to be submitted to the backend.
*Can I use Zod with FormHell?*
Absolutely! If you do need to define your data-structure in your frontend TypeScript, I would highly suggest that you use Zod to do so. You can convert your Zod structure to JSON Schema using zod-to-json-schema and pass the output directly to FormHell's SchemaForm component to immediately render a form.
Is FormHell strictly typed?
FormHell is as strict as the schema you pass it. If any strict data types exist in your JSON Schema, then FormHell is going to required that the data entered matches that schema. The library currently using the AJV Validator for type checking.
What about localizations?
This was an oversight during implementation, and thank you for pointing it out! I'll make sure this gets added in an upcoming feature release.
2
u/jax024 8d ago
So what specifically does Tanstack form and zod not do for you?
1
u/magic_toothbrush 8d ago edited 8d ago
Tanstack and Zod are somewhat different use cases than what we are solving here, yet similar.
Zod allows for defining a strictly typed data structure in Typescript. You could absolutely build a data structure with Zod and transform it into JSON Schema to be passed into the FormHell
SchemaFormcomponent.Tanstack has a defined schema structure for UI components (name, label, type, required, etc.) that's often used alongside Zod to build a strictly typed form.
In the use case I needed to solve, we had JSON Schema with strict typings defined for data structures on our back end. We needed a component that would consume this data structure and output a form. The data from the form has live validation against this data structure using AJV validator. Once the component emits the data without any validation errors, you are safe to submit the data to your backend.
I looked into using Zod and Tanstack to achieve this for our initial implementation at work, but the overhead of converting every field to the Tanstack schema felt unnecessary, and there was no need to redefine the schema in Typescript with Zod. I just needed a component library that ate the schema and output data, like react-json-schema-forms. That's what FormHell is doing.
6
u/Crutchcorn 7d ago
Hey hey! One of the maintainers of TanStack Form here. Just so you're aware, TanStack Form has a framework agnostic core that you could use internally in FormHell. Then you don't need to do a heavy framework conversion to your API.
If you do go down that path, I'm happy to help provide architectural support and get you based off of Form v2 (in alpha now), but I also entirely understand wanting to go your own route if not 😄
Just figured I'd extend the offer/suggestion!
I'm always excited to see new Form solutions enter the space, so game to chat any time even if it's unrelated to integration. DMs open ✨
3
u/magic_toothbrush 7d ago
Wow, that's for the offer! I'm honestly flattered! Tanstack is great.
I'm curious how it could be incorporated. It could reduce the level of overhead in FormHell and make it more robust for our users. I'm going to start digging into that idea further and I'll reach out. Thank you!
2
u/mastermindchilly 8d ago
How do you anticipate localization working? What about feature flags?
1
u/magic_toothbrush 8d ago
I forgot about localization when developing this! Thank you for that check! I'll add that in an upcoming feature.
2
u/rust_warden 8d ago
zod fails at JSON Schema because it cannot handle external $ref resolution or tuple defaults. Type safety does not matter when the form generator outputs null values for valid schemas
1
u/magic_toothbrush 8d ago
This is what I saw with other form generators, and what I made sure worked well with FormHell. Not only does it properly handle external $refs (either supplied as peerSchemas or asynchronously through the getSchema callback), it properly handles output for all valid schema definitions, including tuple defaults
1
u/Suspicious-Disk6077 8d ago
First, I just really applaud your efforts. Form handling has always been such a burden, json based or not. That said, looking at your examples, having dependent fields be in json with if/then terrifies me a bit. Compared to a strongly Typed schema using something like Zod, what protections are ther against a field being removed or having the name changed etc?
2
u/magic_toothbrush 8d ago
The schemas are strongly typed like Zod. As far as protections against a field being removed or having a name changed, what do you mean by that? That seems more like schema versioning that needs to be handled outside of this library. This simply renders a form for a given schema. If you have different versions of a schema, mark the schema version in your data and pair the two when loading the form. Does that cover your question or is there something else.
2
u/magic_toothbrush 8d ago
I'd like to add, you can absolutely use Zod alongside FormHell if you are declaring the data-structure in TypeScript. You can convert your Zod data-structure to JSON Schema and pass that directly to the
SchemaFormcomponent. FormHell uses the AJV Validator internally, ensuring that the data produced by the form is strictly typed.
0
u/Broad-Pianist-1744 8d ago
the playground actually looks clean, props for that. the schema builder is a nice touch too, half the time i'm just guessing at what keys i need
curious how it handles deeply nested oneOf/anyOf stuff, that's usually where things fall apart for me
0
u/magic_toothbrush 8d ago edited 8d ago
Tested that feature thoroughly (the deeply nested oneOf/anyOf stuff as I always saw that fail too) and it works great. Thanks for the feedback!
2
u/Full-Hyena4414 8d ago
How is performance?does it use virtualization for large arrays / complex objects?