Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: React Hook Form – Simple Form Validation (react-hook-form.com)
112 points by bluebill1049 9 days ago | hide | past | web | favorite | 72 comments





I strongly recommend to automate form generation based on JSON schema what will enable zero coding for maintenance tasks like e.g. synchronization with model changes.

As form code is the most important entry point for security flaws in web applications it is also the most expensive and it is not a good idea having to touch production code for every little backend change. This looks like PHP coding 15 years ago. Do not do that.


In my experience, this is a pie in the sky dream - orchestrating dropdown loading and lazy loading becomes challegning. Dependencies between inputs become impossible (if this field is filled [or set to value x], show this section of the form, if this field is of value x, only allow values of a, b or c in field y).

Not only this, but I think generally when a backend change happens you want to be aware of it (and fail early, probably in the test/integration phase!) - leaving it potentially as late as runtime could be devastating.

For very basic forms generation from a model is fine, but I think it hits its limits pretty quickly. Imo generating a model from a schema is an okay halfway house.

Regardless, this tool seems pretty nice, and could save me a little boiler plate!


Agree, also there is also UI and UX's input on how the form should behave and its looking feel, it's not always just couple inputs and a submit button :)

I agree somewhat.

A plain data format (like JSON) should be used to generate Forms, so your client/server side validation is always in sync (DRY).

But this isn't mutually exclusive. You could use this component and generate the implementation (or just plainly transform your data into this with a function). Especially since it leans very heavily on the HTML standard, which has several advantages.

Having a look at the code examples and documentation it would seem ergonomic to just feed JSON into a component that uses this.


I agree. the lib itself is primitive enough for you to build a JSON formate to generate forms. here is an good example: https://github.com/start-at-root/react-breeze-form

Can you point to a real world example of what you mean?

I think I have heard of something similar but it didn’t seem to have caught on in any major web frameworks that I know of (strongly typed json API server which generates runtime validators on frontend and backend). Even then most people want control over the presentation of the form and wouldn’t want to create fields from the schema (e.g. a number type is sometimes a slider and sometimes a drop down)


There's a few people trying to build libraries (https://github.com/rjsf-team/react-jsonschema-form) but there ain't any magic bullet. For this project (https://github.com/mickael-kerjean/filestash), I built my very own as no other library would work for what I wanted

A friend of mine build a solution like this:

https://laraform.io/

If I have a form anything more complex than a login page, then I usually use some kind of generator based on a schema.


interesting project! thanks for sharing

I was not writing about a specific product but about a way to implement form generation. Most web frameworks come with the basic building blocks.

I'm in the process of ripping a system like this out of our main onboarding application. The idea sounded so great: "Just add another object to an array and the form field will magically appear with validation, persistence, etc". The reality is that business requirements turned it into a ton of special case "if" statements. I'm going to avoid that for the next go-round.

yea, I have been working forms for a while, there is hardly a page where a form just couple inputs and a submit button. There are conditional display, design and UX requirements. I can see this working for a one-page simple form.

If all goes according to plan, we plan to use your library in an update to our onboarding process. You've even helped me in your GitHub issues, so you are very appreciated!

oh sweet! that's great to hear. my pleasure to help.

The latest JSON Schema draft introduces some nasty patches that fix the previous draft's limitation. It's even more confusing, it's not designed to generate form even if people have tried (some things can't easily map to form) and the latest spec said so.

agree. it all looks good on paper until the requirement and design changes, then you are in world of pain.

Application like configuration UI is probably fine, for example, system preference. It has sort of generic UX.

yes, the right tool for the right job.

everything is about pros and cons. there is no silver bullet for building form if you enjoy building a form with JSON schema good for you too. Thanks for checking it out tho :)

At an earlier job, I got so annoyed with the constantly changing requirements I developed a form generator. With AngularJS. I wish I could've saved the code, it was so beautiful and horrible.

it's beautiful when it all works, it's horrible when requirements changes.

How on Earth does this remotely look like "PHP 15 years ago" to you?

lol

I’m going to hijack to request some help understanding whether hooks are a good thing or.... a mediocre thing I just have to accept. Here are my questions:

1) Is it just me or so hooks really push you to commit to either “state comes from props” or “state is held internally” but you REALLY can’t mix the two?

So, if I have say, a searchable select box, I must either A) be stateless, and let some other part of the system store the user’s typing, or B) use a state hook, but NEVER react to state changes coming in from outside.

I.e. I am tempted to use useEffect to notice my props and my state being out of sync so I can sync them back up, allowing either the user or the backend to provide changes. But that also feels bonkers.

Doing the same thing through message passing also seems bonkers, React was created to replace having to pass messages around to every component that needs updates, wasn’t it?

2) Is there any point to useCallback? Is it literally the same thing as returning a function from useMemo?

3) Is it just me or is useRef kind of a horrible hack? Lots of articles tell me to do myRef.current = myState in order to hack around the fact that state changes don’t take effect until the next tick. But now we no longer have a single source of truth, and introduce lots of sync bugs. Also have to type .current everywhere.

4) Should I be using useEffect instead for solving the issue with #3?

I just have this sinking feeling that at least one of useRef, useMemo, useCallback, and useEffect shouldn’t exist, but I am only three months in to React and I can’t really see the forest through the trees.


1) You could mix the two around. E.g. using a state hook and the imperative handle hook. By using the imperative handle, we could update the state from the outside by exposing the setState function.

2)There are several points, but I think the most important one is simply just to save time instead of using useMemo as passing callback to child components is pretty common. And yes, it is the same. The official docs literally said that. useCallback(fn, deps) is equivalent to useMemo(() => fn, deps). [0]

3)You can call it a hack I guess. If you don't want to wait for rerender, you can keep a value inside a ref! While class component can just create a property, function component doesn't have that. That's where the useRef came in, and that's just one use of useRef. I'm not really sure about the articles you mentioned. I never faced a use case where you would use a state and also keeping it inside a ref, can you share an example link maybe?

For the .current part, since refs is originally used to access the DOM. And the DOM node could change for whatever reason. To access the node, we use .current.

4) It depends, but I don't think keeping two things in sync using useEffect hook is a good idea. I'm not really clear about the issue, so I can't say much.

After using React for a while with class and lifecycle, I think all the available hooks is really nice. Feels like we got a fresh wind while developing with React. Using hooks and not have enough contrast to make me feel I can no longer code React without hooks. They let you reuse and share the same logic for different components or projects easily. Less code to read, and for me, functional component with hooks is way easier to read compared to a class component.

Refs: [0] https://reactjs.org/docs/hooks-reference.html#usecallback


This is a good guide for "thinking in hooks": https://wattenberger.com/blog/react-hooks

You can combine whatever inputs you want, whether props or internal state variables. Hooks are basically a way to specific "do X whenever any of Y variables change", regardless of what those vars are.


I have been doing React development for a good amount of time now and I really like what hooks allow. It does diverge a bit from classic OO ideas though, which can be tricky to wrap your head around the first time.

Hooks do a good job of nudging you to make better decisions about how to design your app, primarily by making bad decisions harder to make. This feels bad initially but once you get it, I think its better.

That said, lets address your issues:

1. Yes/No. There is no reason you cannot have both props and state effect your component, however I don't think thats your question.

If you need something outside the component to effect what is typed into the box, (e.g. the app can clear the text) then yes, you should be passing the text in as a prop, along w/ an onChange callback prop for when the text is changed within the component. I think of it as, if the state can be changed somewhere else then it doesn't belong to the component, and is thus a prop. Note, the options could be filtered in the component or not, also up to you.

2. I agree with this question. The main use I've found of useCallback is to avoid triggering changes to other hooks. ¯\_(ツ)_/¯ I think react team members have even asked about how people use it: https://twitter.com/brian_d_vaughn/status/117435997560009113...

3. useRef is great. It allows you to store state which does not trigger re-renders. This gives you a finer detail control of your component. I would not use it to "hack around the fact that state changes don’t take effect until the next tick" though. I think it would be bad practice to have to think about when state changes take effect. (This might be one of the "making bad decisions harder to make" moments)

P.S. I agree about typing .current everywhere, but it makes sense from a JS perspective. useRef is simply keeping track of an object instance and you are accessing a member of that object. I'm not sure if it has to be 'current' or if thats just convention (anyone know?).

4. I can't answer this without an example. Generally, if you need the value to render, you either have it via a prop or it it is already stored in state. If you need to transform that value in order for it to look right, you do that inside your function. If it is a complicated calculation, do it with useMemo, so it only has to be done if your value changes.

If something causes your state to change, you should just update the value and then allow it to rerender, thus it becomes the already in state case. Those changes should really only be part of other actions though, not your render function itself.

So that was long winded, but hopefully useful. I think hooks are good and generally use the following heuristic: - useState: state which causes rerenders on change

- useRef: state which does not cause rerenders on change

- useMemo: calculated state based on other props/state (only needed if the calculation is expensive)

- useCallback: useMemo for functions :p

- useEffect: Do something based on state or lifecycle of component (e.g. mount/unmount)

(edited for formatting)


I've never seen a benefit in storing a form state in react state, forms already hold a state in the DOM, you can read, update and validate it (https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Fo...)

for example, after a form submit event, you can do

  const elements = [...e.target.elements].filter(el => el.name); // all form elements with a name
  // invoke onSubmit prop with form data:
  onSubmit(
    elements.reduce((o, el) => ({
      ...o,
      [el.name]: el.type==='checkbox' ? el.checked : el.value
    }), {})
  );

Part of the point (from a React perspective) is that everything in a React UI is driven by the data - so your data (state) should always control the UI.

If you store some state in JS variables, and some in the DOM (forms), then that's not true anymore. That's not necessarily a problem if you're expecting it (uncontrolled components are a valid React paradigm) - but if you're expecting controlled components, but some of them aren't, then you can run into trouble.

Also, once you're used to controlled components, it actually feels like a hassle to keep the data in the DOM - you have to constantly be getting it from the DOM to do form validation, submitting, field resetting, etc.

Again - I would say that neither is more right or wrong; but it's more of a style choice.


This is a really good reply! In fact, React hook form is based on uncontrolled components, I guess the mainstream is still controlled, but I would like to give some fo the love to uncontrolled and explore the benefits from it.

import React from 'react'; import useForm from 'react-hook-form';

function App() {

  const { register, handleSubmit, errors } = useForm(); // initialise the hook

  const onSubmit = data => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstname" ref={register} /> {/* register an input */}
      
      <input name="lastname" ref={register({ required: true })} />
      {errors.lastname && 'Last name is required.'}
      
      <input name="age" ref={register({ pattern: /\d+/ })} />
      {errors.age && 'Please enter number for age.'}
      
      <input type="submit" />
    </form>
  );
}

here is an code example, there is no local state.


The whole point is decoupling Dom state and Application state, React keeps the two in sync via the reconciler, and you as the developer can have a single source of truth. As application complexity grows it gets difficult to make sure your DOM and your javascript are in sync using element objects.

That said Forms are one thing where I don't understand all the libraries built to 'simplify' them. They are not complex, and trying to force the library to fit your use case usually ends up being more burdensome than just writing the extra 20-30 LoC.


Having it in state allows you to react to changes in the form fields for validation, i.e. username availability, password strength, email validity, field character length (think twitter), etc.

Of course you can do this imperatively by manually querying the DOM and getting the input values, but I think it's nice to have the form data in the state to work with and have full control over it.


That’s it! React hook form is basically doing that :) it’s uncontrolled.

Hey author, I’m a long time reader and this is my first post on here! That being said, I absolutely LOVE your library! I’ve been working on a project for a client (a react webapp). I initially built out our signup workflow and delayed completion on that feature until the very end of the app simply because custom validation was a pain (and with tight deadlines, I really didn’t want to write one from scratch). I came across your library about two weeks ago and it fit like a GLOVE! Custom validation was easy, adding in regex expressions was straightforward, and your docs are very clear! Kudos for this project, you’ve made my life much easier. My app happened to also be built entirely with react hooks so this really was a great fit. And the dependency size is much smaller than competitors I was looking at. Thanks for your hard work I definitely appreciate it!

Thank you very much byahya for your kind words and the lovely message. I am really glad could help you out with building forms. This is also one of the reasons why I am so passionate about building open source projects, be a dev only also me to solve particular within a product or project. it's so good we have an amazing community who are sharing their idea and code around the world. It's my 2 cents to give back the community and help out others and of course doing something meaningful in my life :) I really appreciated your feedback and your encouragement, feel free to ask a question or submit issues in the GitHub. <3

Hey author I like this! It's very close to what I use for simple forms, my library `forn`:

    import forn from 'forn';
    
    export default () => (
      <form onSubmit={forn(data => console.log(data))}>
        <input name="firstName" placeholder="First Name" />
        <input name="lastName" placeholder="Last Name" />
        <button>Send!</button>
      </form>
    );
Test it: https://codesandbox.io/s/agitated-johnson-3hv96

Why do you need the register though? Is the hook needed to hold the refs? Is it only for compatibility with React Native or are there other reasons? With forn I use `e.target`, which should not be available in RN.


hey, nice lib you got there :) When I was deciding the API, I did have the idea of just collecting form input automatically (similar to forn), but there are few reasons which lead to the final decision:

1. Support React controlled component. eg some of the popular component libs, they are wrapped input inside their component and it's hard to predict which to include during the form submit.

2. React Native <3

3. Attach validation rules, messages and async validation on the individual field level.


Ha thanks! You described perfectly the limitations of `forn` and why I only use it for simpler forms. React Native is a big pain from tine to time though I barely use it. I also made https://picnicss.com/ so I'm used to use the native form elements underneath and the rest being just a pretty wrap. But yeah, as soon as I add a 3rd party form lib all goes to hell and `forn` doesn't work well anymore.

I'll try it next time I have to deal with React Native!


wow so cool~ https://picnicss.com/ love it. stared the project. <3

I’ve been using this for the past few weeks and I’m very happy with it. I really appreciate the minimalism. It’s easy to have schema driven forms and uncontrolled inputs with this library because it doesn’t have many constraints.

Also, maybe it’s because of hooks, but it feels like less code than usual is required for forms. I once built a massive “multi page questionnaire with conditional logic” feature, using a superset of json schema and a wrapper around react-json-schema-form (the Mozilla one). That was two years ago and a LOT of code (I used a singleton controller to parse local updates and merge them into a global schema). If I had hooks and this library available then, it would have been significantly less code.


wow thanks, chatmasta, I am really glad to hear this great feedback! I would like to put the credit towards React Hook because it really saves us to write less code and not to worry too much about the lifecycle methods.

Hi guys,

I have built a custom hook for form validation, please check it out and feedback welcome <3


Landing page is pretty impressive. Nice work :)

Thank you. I was try to giving everyone some good context why built this form lib.

I've been playing with it for the past ~40 minutes and i really like it.

Can't wait to use it on a real project soon. In fact, i might start converting some older things to it in spare time.

The website and docs are absolutely amazing, best i've seen in a long time. Thank you for doing this!


Thank you so much for those kind words. This means so much to me seriously. I love making things and especially when others are enjoy to use. I will keep improving the site and package. Feel free to ask questions in github :) again thank you <3

This looks great. How about a comparison against https://final-form.org/react ?

Sure I will looking into it and add to the comparison.

Great thanks. One other helpful thing would be to start a project full of pre-wrapped components for various frameworks.

It would be lovely to just yarn add something that would give me Material-UI components already set up. I'm sure others would love a Bootstrap version... etc. The more you can lower the barriers to entry, the better.


By the way I did have a folder of examples as well. Quite lot of them: https://github.com/react-hook-form/react-hook-form/tree/mast... with codesandbox link too

Sure, I've seen examples, but that is different than what I'm talking about. I want components. =) For example, with react-final-form, I wrote a thin wrapper for Material-UI component (example [1]).

While it didn't take me that long to do, it does have some weird edge cases that I had to google around for. It would be nice to not have to figure this stuff out with your framework too and would encourage me to try it out more quickly.

I know that formik and redux-forms are popular, but react-final-form and your framework seem to have a lot of overlap. Both seem to be pretty well done.

[1] https://gist.github.com/lookfirst/558fb2161fd633c7eaab412b85...


sounds good. i will be looking into that :)

That sounds like a great idea! Maybe I should set up some quick templates.

Front-end has gone completely off the deep end. I'm looking at the source code and there must be 4 or 5 dozen modules, totally 5.1kb gzipped! And as far as I can tell all it does is copy el.value onto an object.

What ever happened to care in our profession? What happened to putting the users first? If you are adding 5kb of overhead to your website for this, it is criminal malpractice.


This is like saying that backend's gone crazy because people are loading MBs of frameworks just to print "Hello World" on the screen. Well, yes, but those are just examples, they're meant to be simple to understand, not a realistic use case. React is a tool for building complex web apps and in RL such app would do a lot more things and then it'd start to make a lot more sense using it. If you do something this simple, then by all means don't use it.

> This is like saying that backend's gone crazy because people are loading MBs of frameworks just to print "Hello World" on the screen.

They are not equivalent at all, you can add as much bloat as you want on your backend as long as you scale it. The cost is put on you. Front-end bloat directly affects the user. We used to justify every library addition, now people just add a library for every trivial task to make it slightly "nicer" as if that matters at all.


Issue here is with criticizing over-simplified Hello World examples for unnecessary "bloat" that is not really a bloat in real life. And people do add unnecessary libs in their code, I agree, but that's another story...

I can tell you've never had to work with forms.

I am not exactly sure what are you referring to, but I think this lib is pretty small compared with what is currently on the market, and I have tried my best, time and effort to keep the package as small and feature-rich as it can be, but I love constructive critisim and if you have better solution or reckon code can be improved, please submit a PR and it would do me a favor and also the rest of the community, because I built this not just me for but for other devs around the wrold. thanks

"It Depends" as always. They are already using React - that probably tells you something about the kind of site they are designing. Likely a very interactive web experience or even a SPA. It'll have image assets > 5kb, and probably 100k's of JS. The user needs to weigh up an extra 5kb vs. the developer utility of this.

Mate most websites are shoving MBs down your throat, I’ll gladly take 5kb zipped for a better developer experience.

If doing `obj.firstName = el.value` is too bad of an experience for you that you need to add 5kb to make it better you're going to get to that MBs pretty quickly.

no comment...

It starts to feel webscale only with a K8S backend!

This looks really good. But is there a non-hook version for use in class components? I'm imagining it might look like this:

    class MyForm extends React.Component {
      formState = new ReduxHookForm();

      render() {
        const { register, handleSubmit } = this.formState;
        return (
          <form onSubmit={handleSubmit(this.handleSubmit)}>
            <input name="firstName" ref={register} />
            <select name="gender" ref={register}>
              <option value="male">male</option>
              <option value="female">female</option>
            </select>
            <input type="submit" />
          </form>
        );
      }

      handleSubmit(data) {
        console.log(data);
      }
    }

I have a pure-javascript library that works like that, "forn". No hooks or any local state needed:

https://www.npmjs.com/package/forn


I haven't got a plan to look into class component just yet, but will do in the near future.

I made this one last year. It can be used with class components too.

https://github.com/ozgrozer/rfv


yea would be similar for class component :)

Sorry I don't understand. Last time I checked, hooks are not usable from class components. How can I use react-hook-form from a class component?

Sorry I meant once I made it work, and it will be the syntax



Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: