Video Summary and Transcription
Andy Richardson, a software engineer at GraphCDN, introduces Fielder, a project aimed at simplifying form creation in React. Fielder allows for decentralized form schema and onSubmit logic, making it easier to handle async validation. It eliminates the need for hoisting conditional logic and simplifies rendering and validation. The Fielder library is recommended for exploration but not yet stable for production. The speaker emphasizes the importance of being truthful and addresses the performance and re-rendering capabilities of Fielder.
1. Introduction to Forms and Fielder
I'm Andy Richardson, a software engineer at GraphCDN. We specialize in edge caching on GraphQL endpoints. Check out chandyrichardson.com for more information.
♪♪ Damn, what an intro. Thanks, Yanni. Yeah, so like Yanni said, my name's Andy Richardson, I'm going to be talking about some forms today. I am a software engineer currently at GraphCDN. We do some pretty cool stuff with edge caching on GraphQL endpoints, so if you're into that kind of thing, definitely check it out. And yeah, you can find me online, so at chandyrichardson.com I'll probably pop up. Cool. My boss said that I didn't make a big enough statement about GraphCDN, so there you go, max. If you want to find out more as well, he actually did a talk earlier today, this morning, about GraphCDN and what we do, so definitely give that a peek.
2. Rethinking Form Design in React Development
Forms should provide a simple, guided, responsive, and fast user experience. React currently handles forms differently, with forms as the primary focus instead of progressive fields. I started a project called Fielder to explore a solution where the form schema and onSubmit logic are not centralized. Let me show you the pieces and examples.
But without further ado, forms. So, first thing I want you to do is just think about a good form experience. So, we've all been on bad form experiences, very confusing all over the place. But when we think about good form experiences, we probably think about a simple journey, a guided experience, so we know where to go throughout the form. And also something that's responsive and fast to use.
I think the worst-case scenario is having to go back in a form because you've made a mistake early on. So, if we put that into an ideal flow, almost like a user journey, we're thinking about populating a field, getting told if you messed up, ideally, as soon as possible, and then some kind of progression. And a progression can be move into the next field, it can be the next page in the form if it's a multiple-page form, or it could be the final progression which is a submission.
And this is what it looks like currently in React when we make forms, which is very, very different. Rather than having these progressive fields which are the primary thing we think about, instead we have forms as the primary thing we think about, and we shove everything in a form early on. And it's kind of strange because that's not what we really do with React. Usually if we have things that happen over a series of pages or so on, we wouldn't put all that logic in one place, but with forms at the moment, we do.
So this got me thinking, is there a way that we can make a form where we don't need to put the schema all in one place? We don't need to put the onSubmit statement all in one place. And what if we do that dynamically as we're moving forward as a unit of users going through fields and so on? And, yeah, so that's exactly what I wanted to try. And a few, about a year and a half ago, I started a project called Fielder with the goal to try something like this. And I want to run you through the pieces and also show you some examples and see what you folks think.
3. Creating Great Forms with Fielder
The end goal is to provide a solution for creating great forms without hoisting everything to the top. The key pieces are the form, the field, and progression. Examples will be shown to demonstrate their usage.
The end goal isn't really to get people to use Fielder. It's just so that the next project I go on, I don't have to deal with terrible forms because you all have, I don't know, pushed forward a new library that fixes this problem. So, yeah, this is a proposed solution, but whatever library applies it, doesn't really matter too much.
So, the pieces. So, if we want to create a great form and we don't want to have to hoist everything to the top of the form, first thing you have is the form. But the big difference here is that this is very, very dump. So this is just amalgamation of state and this will be high up in the component tree. And once we declare it, we forget about it.
The next thing is the field and this is our first class citizen. So here we mount the field, we give it some validation, we give it an initial value, and that is, that's basically how we design our forms with fields as opposed to with just one big form. And then finally, we've got progression. And you might think of this as an on submit and it is definitely an on submit, but it can also be an on progress. So if you think about a wizard, if any of you are familiar with that, a form where you've got multiple pages and you're just stepping through, we usually wanna guard that just as much as we wanna guard that final submit statement because there's nothing worse, like we said, than having to go back in a form and fix something somewhere else. So we wanna guard that and prevent progression from happening. So yeah, there's an example, but we can also have some kind of progression which isn't a submit. Cool.
All right, I'm gonna show you some examples. So we'll get hands-on with code and let's see what we can make with those three things. So first off, hopefully you can see this. Yeah, it's big enough. So we've got a username field and we wanna populate it with a value and if the user changes that field or tries to submit and there isn't any value there, we wanna show some kind of error. So, presentational components out the way, that's a completely different talk. The first thing we're gonna do, Declare our field. Pretty straightforward. And then we add our validation. And in this case, because we don't care about the particular event that we're validating on, we're just gonna check the value and if it's not there, we throw an error. And then, as you can see further down, we present that error when it occurs. And then, finally, we just wanna guard that. So, we wanna make sure that that validation is satisfied before we allow any kind of submission. Cool.
4. Adding Async Validation to Forms
Let's add async validation to our forms using Fielder. With Fielder, the validation function is called when there's a submit event, making it easier to handle async validation. This eliminates the need to hoist conditional logic into the form declaration and routing, simplifying the code and improving maintainability.
So, now let's mix it up a bit. Let's take what we have already and let's add in some async validation. So, sometimes this can be quite tricky. I think with Formic, you would have to do an onSubmit, which checks, does async validation, and then write your own errors, or something like that. But, in our case, this is the only change. So, because everything is located with a field, the field just gets told, hey, there's a submit event, and the validation function gets called. And then, we just go, okay, well, if it's a submit validation, let's return a promise, which checks if the username is taken. If it is, then we throw an error. If not, we return, and then the handle submit call will continue and submit. And then, yeah, in this case as well, the only difference now is we just wanna show that we're checking that username is taken. So, those are two still fairly basic examples, and they don't really demonstrate why having things coupled to fields as opposed to forms are really valuable. I think branching is when that starts to change. If you've ever tried to do a form, which is technically more than one form, and you need to split depending on user values, you've probably gotten really frustrated with most form libraries. And that's because we're expected to hoist all that conditional logic up into the form when we declare the form. But then we also have that conditional logic in our routing as well, and it becomes a bit of a mess and very hard to maintain.
5. Forms, Validation, and Rendering
The user provides a region, and depending on the selection (UK or US), they are asked to enter their favorite tea or coffee, respectively. The forms for UK and US have their own validation logic, eliminating the need for conditional logic. The route component handles the rendering of different steps and ordering them as necessary.
So this first example of a form, the user provides a region. And then if they choose the UK, they get asked to put in their favorite tea. If they hit the US, then they get asked to put in their favorite coffee.
Now, in our UK form, because we only want to validate if we take that branch route, we don't need to worry about hoisting it and then doing lots of conditional logic. Instead, we just mount our fields and add our validation. And similarly, with US form, the exact same thing. And the cool thing about this is that, because we're doing our validation at render time and our submit at render time when we're going down that route as opposed to prematurely, we don't really need to add any conditional logic. Because if we take the UK form route, then we're never going to render that field anyway. So the validation won't apply. So it's a lot more straightforward.
The final step is now just having that route component that just composites this. So handles rendering those different steps and then ordering them in the way that's necessary. So you can see here, we render our region select on the first step. That will then call onComplete. And then we move to the second step. And this is where we start doing our branching. And this is the only branching we do. Because we're handling submission and validation low in the DOM, in the component tree, we don't really need to branch anywhere other than when we're rendering.
6. Rendering and Dynamic Forms
The final step is having a route component that composites the different steps and orders them as necessary. We handle submission and validation low in the DOM, eliminating the need for branching logic in multiple places. Treating forms as more dynamic simplifies the process. Check out Fielder if you're interested in exploring this direction.
So it's a lot more straightforward. And the final step is now just having that route component that just composites this. So handles rendering those different steps and then ordering them in the way that's necessary. So you can see here, we render our region select on the first step. That will then call onComplete. And then we move to the second step. And this is where we start doing our branching. And this is the only branching we do.
So if you think about that initial example with Formik, you've got your onSubmit, which will have to branch if you're changing different endpoints to call. And also with your validation, you'll also have to have that conditional logic in your validation. And then when you render, you'll also have to do that branching logic again. Because we're handling submission and validation low in the DOM, in the component tree, we don't really need to branch anywhere other than when we're rendering. And that's kind of the secret, really.
I think that this is one of those things that would have made things a lot easier. And I think it's just, we've gone, as a community, down this route of having forms as this big entity. And I think that maybe it could be a lot simpler if we treat them as more dynamic. So you can basically forget about this. And you can forget about this, all this branching on schemas and on submits. And instead, you can just branch when you're rendering and just declare validation as you would if you weren't branching. So yeah. That's about it, really.
If there was a summarization for this, it's not necessarily check out Fielder, although I'd definitely recommend it if you think this is interesting. But it's more so that let's see if we can get forms going more through this direction. Because I think it has a lot of potential. Thanks.
Passion for UN Forms and Audience Questions
Why are you passionate about UN forms? A client's problem with branching forms led me to explore this. Ignoring my partner while working on forms made me commit to finding a solution. Now, let's move on to the audience questions.
Thank you Andy. Now, if you please proceed me to the Q&A lounge. We have some hard-hitting questions for you. Follow me.
Oh yes. Would you like some water? Oh man, I'd love some water. We didn't bring beer. I think that would've been an appropriate time. Was that 6 PM that it starts? Yeah, I think something like that. Yeah. All right.
OK, so first question before we get the Sli.do questions. What is it with UN forms? What? Why? I mean, as a developer, I understand that there has to be a way to get things done. I mean, as a developer, I understand it's a meat and potatoes thing. You have to do it. But why are you passionate about this? I don't know. I mean, we have to. So Yanni knows this. We have a client who actually was trying to solve this exact problem. And they had forms which were constantly branching. And they had a nightmare trying to hoist all that branching logic. So that's kind of what got me into it. And then after that, I guess it's just, I don't know, when you spend so long ignoring your partner because you're working on forms, it's like you've just got to keep it up now. You've got to commit. Otherwise, she's got questions. So yeah, no. I think just the initial problem that we had with that client really stuck with me. And that's something that I really wanted to explore. Nice. All right, so we have a whole bunch of questions here from the audience.
Favorite Tea and Q&A
You went massively under time. What's your favorite tea? I like peppermint tea. React hook form and CreateFielder have different approaches to validation and submit logic. The UK's passenger locator form is frustrating, especially on mobile.
And you also, you've got a new reason for being one of my favorite people. You went massively under time, so we've caught up on being late. Get in. I'll go.
All right. So what's your favorite tea, then? Oh, that's a good question. I like peppermint tea. Oh, nice. My mom actually used to give me tea in a baby bottle, which is probably the most British stereotypical thing ever. That also explains so much. Yeah, yeah. But no, peppermint tea is my current favorite. Nice.
All right, well, let's take this actual technical question. So have you checked out React hook form? And how would you, you know, why go on CreateFielder? What is the deficiency in Nexus instead of the art? No, that's a good question. That came out a bit later than when I started working on this kind of stuff. And it definitely takes some of those approaches to declaring validation and submit logic lower in a form. It still does a lot of hoisting, though. So things like validate on change, validate on blur, you can't do that on a field. You have to do that form wide and declare that. So I think it's definitely a step in the right direction, though, for sure.
Nice. Well, this is the most popular question. I'm sorry, I have to ask this. It's not a technical one. But have you had any experience with the UK's passenger locator form, and could you please fix it? Damn. Is this the one to get back into? Yeah, when you come to the UK, you have to fill this form. And it is a very frustrating experience, especially on mobile. Yeah, I didn't do it on mobile. I have had experience with it.
React Native Support and Origin Story
The government form stuff is pretty good because they actually force you to do one field per page. With Fielder, the types that we store are basically whatever gets passed from the input element. React Native support requires pointing the library in the right direction. My problem was more the technical side of things, the implementing, rather than the using forms.
It wasn't too fun. Unusually, the government form stuff is pretty good because they actually force you to do one field per page, which turns out to be quite nice. But yeah, no, I personally haven't had too much experience with that other than just using it once.
Nice. So how does this work with TypeScript? Like, can this work with TypeScript? Can you get type safety with this approach? I think it's been, to be honest, this is something that I haven't worked on for the last couple of months with switching roles. But I'm pretty sure we plugged together some stuff so that when you declare like a field name, then we know what types we're working with. The one thing I would mention was that, at least with Fielder, the types that we store are basically whatever gets passed from the input element. So if you're using a number input element, that still returns a string. So we'll store it as a string. If you want to change that into some kind of integer or whatever, you can do that on SubmitTime.
Nice. Does this work with a React Native? Is there anything DOM-specific here that, you know? Yeah, no, it works with React Native. It wasn't super straightforward, but yeah, no, it does.
Nice. What did you need to do to make it work for React Native? What is the kind of platform-specific thing here? Well, Kadi, if she's in the audience, might know about this because I pestered her a lot. Yeah, it turns out, I mean, you'll notice as well, change handlers in React Native are basically everyone just has a different name for each element. It's onChange here, then it's onSelect somewhere else, and so on. So for React Native support, because there isn't a standard library for form elements, it's mostly about you just need to point the library in the right direction, if that makes sense for your library of choice. But there's pretty detailed docs on that.
Nice. All right, so this is a bit of an open-ended. You alluded to this already with a project in the past, but what is the context of the worst form you have experienced, and what was the most frustrating thing? Basically, I guess the question is, what is your origin story? What made you a joker or a Batman? Oh man, well, I was 10 years old, and I was signing up for Facebook. No, I'm kidding. No. To be honest, I think my problem was more the technical side of things, the implementing, rather than the using forms. I just angled it as a user story, because I thought it would sound better as a story. But in terms of to answer your question, I think it's a technical solution, really, rather than a user solution. But there's no big juicy story where you were tearing a hair out and crying in the middle of the night kind of thing? I'm not weird enough to come up with that on the spot. But if I was, I'd 100% make an origin story. I'll come back to you with a post or something like that.
Code Snippets, Slides, and Fielder Performance
There were some questions about code snippets and animations, but the speaker couldn't remember the specific tool. The speaker mentioned finishing their slides yesterday and emphasized the importance of being truthful. Fielder handles performance and re-rendering well, and synchronous validation is synchronous to avoid awkward validation states.
Great. All right. Let's see if there's a couple more questions. There's a lot of questions that are kind of like, I wouldn't say like you know, beside the topic. But what did you use for creating your code snippets and animations. Oh, that's a good question. I found that yesterday. That was code. Can someone shout it out? Someone's going to know it here. What's that? Yeah. Sure. Let's go with that. Something like that. Yeah. Code hike? I'm not sure. I'll tweet it. There's an excuse to follow me.
Andy, are you saying that you made your slides yesterday? I'm saying I finished my slides yesterday. I finished my slides this morning. Most of us don't admit it. But Andy here, you know, he tells the truth and truth only.
How does Fielder handle performance and re-rendering? Is there anything particularly you need to do? Are there any gotchas that you had to solve? No. So one thing I worked to make sure was that synchronous validation is synchronous. And that's the case. That's something that I tried to contribute back to Formic before I started working on this. And I wasn't able to just because there was a lot of stuff going on at the time. But yeah. So synchronous validation is synchronous. You're not going to get those awkward like middle states where valid is true, but then the change event happens. So validation hasn't run yet.
Fielder Library Status and Project Availability
That's only for async validation. Anything synchronous is instant. There is a repo with a performance benchmark. The current status of the Fielder library is recommended for checking out, but not stable for production. Adding new fields to forms may cause issues if all fields have the same name. The speaker will be maintaining the project for a few more months. Fielder can be found by searching online, on GitHub, or on NPM.
That's only for async validation. Anything synchronous is instant. And there is a repo with a performance benchmark. So if you want to check it compared to Formic, if you're into performance benchmarks, then there's that. I can't say that I've ever really had a performance problem rendering forms, at least one that required heavy benchmarking. So I'm glad that they exist.
Yeah. Yeah. There's definitely a tick box you can put on your repo readme, the fastest form library. Oh yeah, I like the numbers at least. Exactly. Well, I think that kind of leads us to the next question here, which is what is the current status of the field of the library? Do you recommend us use, you said. You would be OK with another library taking its space? Totally, yeah. Yeah, so what's the status of the project? Would you recommend using it? Would you use it yourself? I'd recommend checking out. I've used it myself for a couple of projects. I think, yeah, I'd definitely say people check it out, but don't feel it's stable for prod. There's one use case which isn't covered, which is when you add new fields to forms as you go, add more, add more, add more. Basically, the problem with that is if you're declaring fields and using the name as the unique identifier, then if all your fields have the same name, you just have them overwriting each other. So if you need it for something like that, maybe think otherwise. But outside of that, it's pretty stable. I'll be maintaining it for a few more months, at least. Nice.
All right, and let's finish here with a softball. Somebody's teed it up you real nice here. Where can we find your project, Andy? My projects? Like Fielder and so on? Fielder, yeah, yeah. If you search Fielder online. Are you telling them to Google it? Google it, basically, yeah. Yeah, that's exactly it. Yeah, there's Docsite and stuff like that. But GitHub or if you search an NPM for Fielder or whatever.
Fielder Search and Conclusion
When searching for Fielder, it should come up on any search engine. The speaker doubts that it will rank highly, but they have put in a lot of effort to improve its visibility. Let's move on to the next part.
Basically, any search engine you can find, search Fielder, it'll probably come up. I highly doubt that, actually. If you type Fielder, can somebody please type it really quick and see what happens? Because I'm pretty sure that it's not going to give you a, I think it's going to give you a baseball player or something. I think it would be first page, because I spent ages, ages doing server-side rendering to get it to work so that Google would actually rank me somewhere other than page 50, so, yeah.
All right, we'll settle that score off stage. I think it's time to move on. Thank you so much, Andy. Yeah, thank you very much. Yeah, great talking to you. Appreciate it, man.
Comments