React-hook-form: Remove Dirty Prop

Created on 17 Sep 2019  路  57Comments  路  Source: react-hook-form/react-hook-form

I would like to be able to disable the dirty prop as it is causing unnecessary re renders of components, this is happening when the dirty prop is toggling, I would like to be able to override this by passing a prop of dirtyDisable to useForm which will make the dirty prop either always true or just remove it from the useForm return all together.

wont be worked on

All 57 comments

What鈥檚 the problem is causing you? Just extras render?

the problem i am having is the fact that i have "field arrays" inside "field arrays" to be able to create a table that allows the user to choose different blocks similar to the wordpress editor but with more control for us to stop users being able to destroy the design, the issue is whenever i type in one of the fields anywhere there could be upwards of 50 fields inside of one array which is causing all of them to re-render which is taking like 10 seconds to reload them. yes this only happens when the dirty flag changes but it is not great for us speed wise.

It also seems to be re-rendering all when one field gets added to the touched array too, why does this cause all to re-render.

Edit: I am using the form context component just so your aware.

https://codesandbox.io/s/react-hook-form-basic-ok63f Here is a code sandbox of what i'm trying to do and what is happening might make more sense if i show it.

I'm also attempting to write a wrapper for it for internal use that should make it easier for us to convert older projects that are redux-form, react-final-form based over to your react-hook-form.

I do a console log each time it re-renders.

  1. if each render takes 10secs there is some fundamental issue with ur page or component performance. saving on form state re-render probably not going to solve your problem.
  2. it's nor dirty formstate but touched attribute
  3. react hook form already provide devs with great performance out the box due to the nature of uncontrolled component (while user type is not re-rendering the component)

so I think there is some issue with your component, you can look deeper or share us with a codesandbox and we can take a look for you. At this stage, I am not planning to introduce API change for formstate.

It is re-rendering on dirty change because if you type in a field then clear the field when dirty goes back to false it re-renders, also why is it re-rendering when it gets touched there shouldn't be a reason for it to re-render if it doesn't need to when changing the field any time after that. I will attempt to get this into a video sometime today as i should be working on the project that this happens on. Can we keep the issue open until i can show you what is happening explisitily

dirty indicated when the form is in the original shape or not. it's trigger re-rendering because people who use formState will need to update UI accordingly. touched may not be useful in your app but it's widely used in form building.

yea, let's keep this issue open for a while, see if other users having the same issue, also video doesn't really help much, having working code in codesandbox is probably more useful to investigate the reason why your app is slow.

I really love what you have done with the project though it is much quicker and lighter than the other form modules out there.

thanks :) glad I can contribute my 2cents to the react open-source community

I know you said a video wouldn't help much but i can show you this is just being caused by the touched being updated within the form some reason causing every field to be updated.

Sep-17-2019 11-27-48

as you can see i added a rerender with the field name to each thing and that is how many i get just from changing one field for the first time.

This looks really strange, you only have one field on the screen tho

Yeah in theory everything is inside of one giant array that way we can control it much easier and allow users to be able to add a new block to the page, unless there is a better way apart from having one giant array?

each object in the array has a type of what component it is which resides within the component as a switch so we can render what is needed. all we need to do to add a new block is push into the array a new element at whatever index we want with a type and it will render.

would be greatly helped if you have another idea of a way to do it, this lag and console spit out only happens on the first key of the input everything else after that is like normal, thats why im putting it down to the fact of the touched array that is part of form state.

also, each time you type should only trigger one re-render as well, why this is re-render everywhere?

Would be much useful if you can set up a codesandbox and show how you set up the app/form?

yeah ill see if i can get this into a code sandbox for you there is alot of code within this.

yea sure you don't have to get everything over, just a setup so i can reproduce the issue

ill have a go gimme about an hour and a half ill do it on my lunch break.

no rush at all @The-Code-Monkey we will leave this issue open until we work something out

Hi @bluebill1049 i have had a go it doesn't look exactly like the version i showed before as the styles are off but the content that renders is. if you edit at the section in the image and look at the console youll see the re renders,

image

https://codesandbox.io/s/react-hook-form-form-context-gpphf

sorry the code isn't formatted the best

no worries at all, i will take a look tmr bedtime here :) but i will see what we can work out 馃憤

yeah no worries. good night

I had a look at the codesandbox, I think i can spot couple issues:

  1. you have a lot of forms and you hoist the at the root, which means any state change or update will re-render within the FormContext.
  2. Some of the children are missing keys

My recommendation:

  1. use useForm on each form and collect data use a state management lib such redux or https://github.com/bluebill1049/little-state-machine
  2. If you want to use you should restrict the scope of it, so it doesn't re-render extra components (children) FormContext is really using React context API behind the scenes
  3. not using FormContext but just pass down props individually, at least that way you can use avoid pass down formate

conclusion remove isDirty or any of the form state from react hook form is not going to save you from the problem you are having. Try the above two suggestion, see if your app performance can be enhanced. Option 1 is definitely going to help the performance of your page. let me know how did you go.

I think the root cause of this issue is that you are trying to use react hook form as a form lib and state management library, which it should only do form. That's why you want to use formcontext to grab every field on the page.

Ok i sorta understand the fact that all this does is get the values from the actual field rather than storing it in redux like other forms do, But in terms of re-render again it still only does it when touched gets updated. So what you are suggesting is to wrap stuff around the form context that will handle the state?

Also just to answer your other questions / recommendations, In the full project we are using redux for state management, and there is only one form on the page using the formContext wrapper at the top level.

@The-Code-Monkey so my suggestion will be: you should build forms in React like how you write HTML forms.

you write a form and collect the data and submit to redux/store. That way you isolating the state update and form rendering and give good performance for your page as well. The problem here is not forming state getting updated, it's each state change you are re-rendering the entire app.

hope above statement make sense.

So onChange of X field call a redux action or state action that will store the field value? this would improve performance?

@The-Code-Monkey remove FormContext from the root and having useForm at your Form level and collecting data per form (store form data onSubmit into redux) not the entire page of field. isolate state update per form.

We aren't submitting the form at the point where its slow though its only slow when you change an input for the first time. so adding it to redux on submit isn't gonna do anything. because on submit its going to go straight to an api.

I meant store the field data in redux, and remove form context and using useform on each form group. So state update is isolated to per component. Redux is only storing the data.

oh so update the local state of the component onChange of the field that it is in ill have a go with that see if that changes anything

Yes keep your state update local. Don鈥檛 render the entire app. Use useform on each form component 馃馃徎

So on that codesandbox I sent I would do const form = useForm() then do whatever i needed to do to update state and all that stuff lemme have a go and ill see what i can find. i will still need to do the ref={register} stuff

i have simplified the form to two text boxes using what you said and now when i submit the form the object it returns is blank. https://codesandbox.io/s/react-hook-form-form-context-gpphf i have updated the codesandbox so it looks like this now.

Not sure what i'm doing wrong. Sorry if i'm just being stupid here.

Let me have a look tonight. By the way not each input, a group of input. The screenshoot u shared where a block of inputs. This is where u want to use useform

Nah not stupid at all. We are learning and make mistakes 鉂わ笍馃憤馃徎

Oh ok that makes more sense i will take a look at it within our built cms as its much easier to code in my ide than sandbox. But that makes a lot of sense now. I'll leave this open for now.

Thanks for being so understanding.

So what you're saying is make each block its own little form in theory and then that will update the master form that is stored in redux?

Yea! That鈥檚 right. Redux is your data store. 鉂わ笍

And i have to pass that form down to the children if i want to use the register on it?

Also how would you suggest to submit the form which wraps each block without having the user click a button as obviously we can't do it on change would you suggest doing it on blur?

And i have to pass that form down to the children if i want to use the register on it?

Pass down or use form context, now form context is not at root of ur app. It鈥檚 fine and u can do onBlur and use getValues and submit data to redux

ah ok that makes sense. Ill have a go.

Just out of curiosity is there a reason why the form re-renders each time you type in a field the first time. Is this not something we could wipe out completely? Making the form even better in terms of performance.

it's for formState touched, any form is touched. I think react hook form's performance is great compare with other lib, at this state i dont plan to omit out formstate, because a lot of users need touchedFields to be updated and isDirty formState. It's a choice for API design as well, to omit it out i will need extra props or options or doing things like formState() which is not great.

Fair enough that makes sense, or is there another option of doing a function called useFormState which is imported the same way useFormContext is?

No we don鈥檛 have such an api. That makes api more complicated, my focus is on DX and performance.

Ok no worries was just an idea of something that could come later down the line, in maybe a future update.

Thanks for your help, i think we can happily close this now and say we found the solution in combining it with redux rather than attempting to make the form handle it, The idea of little mini forms wrapper each block container is a much more elegant idea.

Sure thanks for the suggestion.

I would be happy to help maintain the project and support via github issues, i feel like i understand the logic much much more during our little chat.

That would be awesome @The-Code-Monkey 鉂わ笍馃憣馃徎If u find it useful plz star the project and share among your community and friends 馃憤馃徎

Well the company i work for is going to be using it from now on so i will star it.

Great to hear 馃憘 thanks for staring

by the way, you can find help in here as well: https://spectrum.chat/react-hook-form or help others with the similar issue too 馃憤

Was this page helpful?
0 / 5 - 0 ratings