jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.86k stars 2.78k forks source link

onChange and onBlur causes component to re-render #2424

Open diamantisufi opened 4 years ago

diamantisufi commented 4 years ago

I applied formik on material-ui inputFields and I realized that on every key-event or blur, the onChange and onBlur are causing my component to re-render on each event.

This is a piece of code for one of my textInputs

 const formik = useFormik({
    initialValues: {
      label: '',
      .....
      .....
    },
    validate,
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });
return(
<form onSubmit={formik.handleSubmit} className={classes.grid}>
   <DialogContent className={styles.dialogContent}>
     <Grid container spacing={3}>
        <Grid item xs={12}>
          <div className={styles.maxWidthInput}>
             <TextField
                id='label'
                variant='outlined'
                label='Label'
                 name='label'
                 onChange={formik.handleChange}
                 onBlur={formik.handleBlur}
                 value={formik.values.label}
              />
            {formik.touched.label && formik.errors.label ? (
            <div className={styles.error}>{formik.errors.label}</div>
             ) : null}
        </div
    </Grid>
   </Grid>
 <DialogContent>
<form>
)
serusko commented 4 years ago

and what do you expect ? its controlled mode so this it is how it works, you could use uncontrolled mode 2 https://reactjs.org/docs/uncontrolled-components.html

https://material-ui.com/components/text-fields/#uncontrolled-vs-controlled

danieltott commented 4 years ago

@serusko The signature of onChange and onBlur shouldn't be changing. The problem isn't that it's re-rendering, but why it's rerendering. There's also no way to improve any performance via things like memoization, PureComponent, shouldComponentUpdate etc.

sbc640964 commented 3 years ago

@serusko The signature of onChange and onBlur shouldn't be changing. The problem isn't that it's re-rendering, but why it's rerendering. There's also no way to improve any performance via things like memoization, PureComponent, shouldComponentUpdate etc.

Do you have an answer for that?

serusko commented 3 years ago

no with formik there is no way optimize performance because its built with react context which breaks formiks neck, main argument from author from times when we had "figh" between final form and formik its now showstoper for using formik for really complex use cases and you need to switch somehow to useSelector like hook (Redux like usereducer), in the end, once u get how formik works you dont need it and you can create more powerful wrapper for your specific use case its really not so hard you just need to follow inout component interface

serusko commented 3 years ago

btw for text input you can write debounced onchange but you will face some ux issues right after that...

sbc640964 commented 3 years ago

@serusko t.y. There are indeed many issues with using useFormik Do not understand what it is for

Anyway I used the end with Formik component The problem is that I can not take the reset and send functions out of the scope

johnrom commented 3 years ago

You can check out an Alpha prototype of Formik with "useSelector" - like render optimizations built in here: https://www.npmjs.com/package/@johnrom/formik-v3/v/3.0.0-refs2

Basically it removes state from useFormikContext and instead is opted in from Formik's helper components via formik.useState(state => selector(state), comparer);

For Formik's components there is no difference in usage, just a huge performance boost. If you use Formik's state manually by using useFormik, you'll have to manually call formik.useState or use the various convenience hooks provided in v3.

The API is probably not final but I think it's the way Formik needs to go. The only other alternative I know of is proxies but I'm not a huge fan.

There are a few versions on there where I'm building out various functionality, but the most stable one is 3.0.0-refs2.

chuhancheng commented 2 years ago

Is there any other suggest about how improve performance ? In my case, It's would trigger 3 times re-render by onBlur event. So weird.

racsus commented 2 years ago

@chuhancheng did you solve this performance problem?