-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to avoid rerendering? #342
Comments
I'm having the same issue. Typing inside a field is very slow in a form that contains 10 fields, even more with React Native when you create a custom field component with several children components and it internally uses the setFieldValue on a TextInput. This is because every time that a key is entered all the children components of the Formik component are re-rendered. Is there any way to avoid this? |
I am also having the same question/issue, although not running into any visible performance issues during development. |
While performance is rarely an issue on forms, I've occasionally hit this issue on really big/complex forms with custom nested components. The way I've gotten around it is making a form field component that tracks its own value state (setting only its own state |
I actually have a more agressively optimized version of Field that uses shouldComponentUpdate prevents rerenders on “vanilla” inputs (i.e where the component is a string). I think it’s time to write that up in a recipe and add it to core |
@jaredpalmer That would be fantastic. I'm running into this issue myself using a bunch of custom components (and lots of React-Selects). In particular the the repainting of the react-select elements is obnoxious because the little X and Toggle chevrons blink on every repaint. :( +1 for a more optimized Edit: My issue had nothing to do with Formik. Still +1 for more optimization :) |
In react native I do this. export default class FormikTextInput extends React.Component<
Props,
$FlowFixMeState
> {
props: Props
state: $FlowFixMeState
state = {
value: ''
}
handleChange = (value: string) => {
if (this.state.value !== value) {
// remember that onChangeText will be Formik's setFieldValue
this.props.onChangeText(this.props.name, value)
this.setState({ value })
}
}
render () {
// we want to pass through all the props except for onChangeText
const { onChangeText, icon, wrapperStyle, ...otherProps } = this.props
return (
<View
style={[
icon && { flex: 1, flexDirection: 'row' },
wrapperStyle && wrapperStyle
]}
>
<FormInput
onChangeText={this.handleChange}
{...otherProps} // IRL, you should be more explicit when using TS
/>
{icon && icon}
</View>
)
}
} |
You can try this out with Formik 1.0.0-alpha.1's new component |
@jaredpalmer can use it in react native? |
@jaredpalmer Thanks it's working smoothly now |
Not yet. Let me make an issue for that. |
npm i formik@next |
I also have performance issues, when using |
I'm experiencing this issue as well with 1.0.2. I was migrating away from mobx-react-form because I liked the render props of Formik but this re-render performance is definitely an issue. It's not an issue with mobx-react-form probably because MobX updates are so optimized. I'm using custom Inputs like material-ui so your note "I actually have a more agressively optimized version of Field that uses shouldComponentUpdate prevents rerenders on “vanilla” inputs " mentioned above won't work unless I'm missing something. |
This is still happening with RN. Using the ff. "formik": "^1.0.2", |
having same issue, formik 0.11.11 yup 0.24.1, form has like 5 inputs and things are very sluggish. Upgrading formik didn't make any difference. Is there a way to use debounce with formik? It's very needed feature... |
I have the same issue, tried memoizing the error object but Formik seems to update the error on all fields. |
same thing here with the most current formik / yup - every keypress causes all inputs to rerender when using schemaValidation but using field-level validations don't. should we open a new issue? |
I think so |
I'm having this problem too.. |
Same here |
Unsurprisingly, it is significantly faster with |
I've been looking at the Lines 265 to 285 in a35fba4
Formik could avoid extra renders if:
The obvious downsides are:
For these reasons, maybe we could be given the ability to provide our own function to override some or all of the functionality of The alternative is for us to do the Anyway, just trying to throw some thoughts out there. The other thing that could be done, of course, is just to have synchronous validation, which I know has been considered. But that isn't exactly ideal either, because it would be render-blocking. Maybe we just need to wait for Suspense... |
Any progress on this? Still have serious issues on a very small form (5 inputs and a select), I set |
@evark Hi there, any chance you could share your solution via codesandbox? 👀 |
|
@dacopan I did try FastField in my scenario, however it doesn't prevent other unrelated fields from re-rendering. Check this |
@Arthur-Conan-Dog I would make sure you're passing the |
My suggestion is to simply not use formik v2 ... I didnt test the performance on the new version. I used the milestone version and I wasnt satisfied as well with the architecture choices, but maybe it got better. The problem is that, if you have all the form data in a CONTEXT ... you will always re-render everything ... so if you have a huge form, super complex etc, you will be screwed. To simply add memo and stuff to everything, it is just bad in cases of huge forms that involve complex features like modals and such. Imagine an amazon payment wizard process using formik, you would never use it. I dont know if the new v3 version improved this ... but I created a form wrapper on redux, it simply works, and no issues. I believe there are more libraries that use redux ... this way you avoid re-renders. I went on this path in order to integrate better with rx redux observable as well. |
@lucastschmidt there are definite downsides to using Context. Formik is following the path of React itself. There are other packages that do things like use Redux and other tools to manage form state, but we're sticking with straight React hooks. As of right now, the rendering problem is known and we haven't found a way around it without:
I'd like to add that many of the performance issues with re-rendering can be mitigated by using hooks correctly (avoiding objects/functions which are regenerated on every render), and splitting forms into smaller chunks or pages (less to re-render per page). Memoizing things that otherwise wouldn't need memoizing should be the last resort, and is only usually necessary when the fields themselves are extremely expensive. The "promise" of context and generally sticking with "vanilla" React is that React itself will eventually optimize and abandon renders that do not result in any changes with concurrent mode, speculative rendering, or whatever method they end up implementing. Sadly, that hasn't yet manifested. |
+1, this issue should be re-opened again .. I'm facing a huge performance issue in react native. |
Based on ideas from this thread and many others from whole internet I'm using this kind of solution for that problem: I wrote a simple "wrapper" for each field, like that:
and my SimpleField component looks like that:
I'm using react material UI so some tags are custom created as styled (ex. CondenseTextField)
and as long as we pass primitive values to component, that our field is not re-rendered. Moreover, I've added debounce function for onChange callback:
so as you can see I'm calling handleChange event from useFormik() 500ms after last keypress (input value) into a field. |
I have migrated to React hook form and I'm totally satisfied with the results. |
does anyone know if this issue had a solution? FastField is not a way to go for me, my Fromik implementation needs to be the useFormik hook, is there a way to cut that lag on each keystroke? |
@Cuantico Tbh did the same approach as Adbel and moved to React Hook Form. Tried my best to make Formik listen, but I guess due to the form state being kept in a single variable, the rerenders still take place |
Yep @Cuantico I created my own custom lib using redux, but we only used internally, not 100% stable .. hopefully one day we can open source when we have time ... but ideally there are multiple good libraries out there. Check the source code, and the issues open before migrating, to be sure it is not context based to store info. |
@lucastschmidt @AlanKrygowski thanks, finally I could use the FastField and pass it my own Input component in the props: , so I changed the useFormik to Formik implamentation and include the validateOnChange and the validateOnBlure to false, also validateOnMount to true in order to run it at low priority. the performance now is acceptable. |
Formik is telling the form to render in every change. When you press a key, the context change, so Formik ask to all controls render again, and it is ok. This brings some performance issues if you not do anything. So you can use in your components shouldComponentUpdate() where you decide if no changes has made in control, to not render again. This way performance issues dissapears, because you avoid rendering. Another way is to use Memo or PureComponents. |
Setting I've noticed in the flame graph that for some reason, when using Yup and |
I am on the process of overhauling the form system of our platform baseline and Formik would likely be a good fit, however, we need to support really complex form scenarios. So right know I find that we have two deal-breakers:
@johnrom: I know that there is another issue tracking (2), but looks like it is not being addressed at the moment, right? Also, would you mind giving us an update on how v3 is going? Thanks! |
Oh, I see that you now use use-context-selector. I'll give it a try on the next branch, but this sounds very promising! We will definitively be keeping an eye on this and once v3 is more stable we may even consider some kind of extension for the point 2 that I mentioned about the validations. Amazing job, really appreciated. Thanks! |
Yep! use Context Selector is great but unfortunately it doesn't provide any optimizations or render safety (esp. in concurrent mode) outside of the Context children so it is limited in its efficacy. The question that remains is whether that limitation matters. |
I am using formik with react bootstrap form. having the same issue. Any solution? |
@shamim-apex a complete solution for v3 is being actively worked on here: #3089 |
move to react-hook-form and material-ui |
Advice for people researching which libs to use and interested in react-hook-form - look into something like Tailwind instead of Material UI. Material uses controlled components while rhf relies on internal component state and context. You will have to wrap all of your input elements in a Control component in order to make it usable which adds a noticeable layer of complexity. |
You can try in formik SetFieldValue('fieldname', value, false) you can set shouldvalidate to false |
Hello, guys. Having the same problem. Using nested fields. The problem is all form(and all fields) rerenders on every keystroke. The possible solution I think is to add possibility optionally rerender form if value of some field changes. |
Hey it seems like you really solved it, can you by any chance share a demo- github repo/stackblitz/anything so I can see how you constructed your form and everything because I'm stuck on this issue for a long time and have a really long form and it would help alot if you can share with me :) |
the main issue with formik creating lots of renders is how it calculates the state of the form when validating.
these renders are causing terrifying issues with performance on large forms especially when a user types a lot of characters. I've made a gist with a way to debounce the validation.
with debounce validation
let's say a typical input (eg. mail) will have 20 charachters. you can save about (60 vs 22) about 40 or third of the renders. so in terms of UX. it's the best experience, as the user can type freely. and after 200ms from the "last" keystroke, it will validate the form. https://gist.github.com/AlonMiz/e583946d3978de691ed53cece972e1a1 |
how do you handle the errors and touch functionality provided by formik in this case, kindly guide? |
Question
Hello!
Formik library have built-in tools to avoid rerendering all form fields, after changing one of this fields?
The text was updated successfully, but these errors were encountered: