Skip to content
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

FieldArray slow on large data #2296

Open
totaland opened this issue Feb 19, 2020 · 17 comments
Open

FieldArray slow on large data #2296

totaland opened this issue Feb 19, 2020 · 17 comments
Labels

Comments

@totaland
Copy link

❓Question

I have a form that renders 1000 checkboxes. I use FieldArray to do it however the form getting a very slow response after clicking on the checkbox. What can I do to improve the performance and make it smoother and not feel cranky? Many thanks

image

@totaland
Copy link
Author

@jaredpalmer any suggestions mate?

@totaland
Copy link
Author

totaland commented Apr 3, 2020

Hey, I find out how to do that. @jaredpalmer it will reduce the lag of the form even if you use 1mil checkboxes. Inside the FieldArray you implement the react-window. You can either use a react-window or build one yourself.

@stale stale bot added the stale label Jun 2, 2020
@sibelius
Copy link

sibelius commented Sep 4, 2020

is this fixed?

@totaland
Copy link
Author

totaland commented Sep 6, 2020

No, it is the same, just use the workaround above

@alexandreh92
Copy link

can you show us the workaround code @totaland ? thanks

@totaland
Copy link
Author

totaland commented Sep 29, 2020

In your form you render the FieldArray item:

{<FieldArray name={'searchResult'} render={ListResult} />}

Then you have this ListResult like this:

import {FixedSizeList as List} from 'react-window';
const ListResult = () => {
    return (
      <List
        height={300}
        itemCount={length} // this can be any number of items 1mil maybe
        itemSize={30}
        width={'100%'}
      >
        {Row}
      </List>
    );
  };

const Row = React.memo(() => {return <YourActualComponent />}

From memory, you can't replace Row with React component, it only works with a function expression or arrow function, as Row like above code.

@hstevanoski
Copy link

hstevanoski commented Sep 29, 2020

In my case, this workaround isn't particularly useful.
Although the data is a simple array of objects, beside checkboxes, I render input fields, dropdowns etc, which means rerendering on every keystroke is expensive and I notice significant lag for ~20 components (which is even worse on an older PC, obviously).
It sucks because some libraries (like prime-react) just won't work in an uncontrolled manner, which means you are pretty much stuck with (a library such as) Formik.
Using FastField doesn't make much of a difference either.
The only thing that helps reduce the lag is disabling validation on blur and on change (inside <Formik>), but that's not an optimal solution.
Please fix this as soon as possible! Thanks!

@totaland
Copy link
Author

My form has all of the above that you mentioned too. Do you have a codesandbox? I can have a look if I can make it better.

@hstevanoski
Copy link

My form has all of the above that you mentioned too. Do you have a codesandbox? I can have a look if I can make it better.

Thank you very much!!!
Unfortunately, since it's not a private project, I can't share the code. All I can say is that it's a somewhat complicated form.

@sidwebworks
Copy link

Any updates on his one? I am facing the same lag issue with multiple form fields inside the field array component.

@karanaditya993
Copy link

Hey all, I'm following the progress of this on #1895 , which seems to be a similar issue

@sudipstha08
Copy link

sudipstha08 commented Aug 26, 2021

Encountered the same issue while dealing with form with large number of form fields. I solved it with this workaround.

  const FastTextField: FC<IProps> = ({ name, handleChange, value }) => {
    const [localValue, setLocalValue] = useState("");
  
    useEffect(() => {
      value && setLocalValue(value);
    }, [value]);
  
    const debouncedValue = useDebounce(localValue, 200);
  
    useEffect(() => {
      handleChange(localValue);
    }, [debouncedValue]);
  
    return (
      <TextField
        name={name}
        value={localValue}
        onChange={(e: any) => setLocalValue(e.target.value)}
        type="text"
      />
    );

And use this fast field something like this

 <FieldArray name="person">
    {({ push, remove }) =>
      formik.values.person.map((item, idx) => {
        const errors = formik.errors.person[idx];
        const touched = formik.touched.person[idx];
        return (
          <div key={["person", idx].join("_")}>
            <FastTextField
              name={`person[${idx}]`}
              error={touched && errors}
              value={item}
              handleChange={(value) => formik.setFieldValue( `person[${idx}]`,value )}
            />
         </div>
        )
      })
    }
  </FieldArray>

@remoideas
Copy link

Only add

validateOnChange={false}

to Formik tag

@nwabueze1
Copy link

Thanks remoideas, it setting validateOnChange=false did the trick for me

@arturowin
Copy link

arturowin commented Jan 30, 2023

import { FieldArray, FastField } from 'formik';

Replace the standard formik <Field> component with the <FastField> component, as it will minimize the number of re-renders and improve performance.

@Sanketkondhalkar
Copy link

Only add

validateOnChange={false}

to Formik tag

First it takes 16 second for rendering but now it just takes the 8 second for a rendering thank you for this awsome solution 😇😇

@ChayaninSuatap
Copy link

  1. validateOnChange={false}
  2. Turn what's inside map function into a component. Pass props as you need.
  3. Wrap the component with memo()

These steps give me almost zero lagging time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests