Closed joonhocho closed 6 years ago
Use <FastField />
@jaredpalmer Can I use FastField in place for all Field without any changes? Any documentations on this? Thank you!
<FastField>
is best used on pure fields that don't impact other fields either by changing another field's value or error message. State is kept locally in FastField and then synced up to the top level <Formik/>
component once onBlur is called.
@jaredpalmer Thank you I will try and report back if there are any issues.
One issue I have found with <FastField>
is that since the state is synced on blur, if the form is submitted by pressing Enter
in a field, the latest value of that field won't be synced before submit. That's particularly annoying, and I haven't yet found a work-around that doesn't involve patching FastField :(
@hmaurer Could you wrap handleChange
in a function that triggers onBlur
if the Enter
key is pressed? (As a temporary fix)
You can use shouldComponentUpdate to wrap Field to optimize perf
I have the same issue than @hmaurer with <FastField>
. Please, is there going to be a fix? or a nice workaround?
For now, I'm just using something like:
({ field, form, ...props }) => {
const onKeyDown = (e)=>{
if (e.key == "Enter") {
e.stopPropagation();
form.setFieldValue(field.name, e.target.value, false);
}
}
//more code here
return <input {...field} onKeyDown={onKeyDown}>
}
using create react app and semantic ui i built ~40 fields. input is very slow whilst running the app in dev mode. but when i run yarn build and run the app with serve -s build, there is no delay in input fields. can i expect the same results in whilst running on a production server?
Use FastField. It works now.
I have 1206 fields on the page and i am using FastField as well and it's veryyyyy slow any suggestion to improve this?
Basically i am using table and all 200 rows are inline editable with 6 columns. That takes too long to compare in shouldUpdate
@anand-neema formik is really not designed to be performant on forms with that many fields or spreadsheet-like UI.
It may be a noob question. Even though how can I use FastField If I use a third part input component like material-ui's TextField
@anand-neema I imagine if it really is a table, each row would have the same fields with a different entity being edited (like a bulk editor). In this case, I would allow a user to only edit the rows they need to by clicking "Edit Row" and replacing that row with a Formik-ized version of the row. Multiple instances of Formik can be applied to each row. On each submit, turn that row back to the static version of the row. I still don't think it will be fast, but it might be faster. You can also add pagination to help.
Think of it like this
const MyTabularForm = (props) => (
<table>
{props.data.map((row, index) => (
<tr>
{props.editing[index] ?
<FormikRow {...row} />
<NonFormikRow {...row />
</tr>
)}
</table>
);
@wellyal check out the discord for quick questions / help or try opening a new issue if you think you've found a bug or a need for more documentation.
@johnrom thanks for your suggestions. I Was planning that only and yes it's fast now...... But was thinking about validation stuff consider this scenario
I have mandatory field in a row and then i have click on another row, how will i maintain that error and disable the submit button ...as now field is unmounted and i am showing non formik field instead of formik field... how will error will get persist ?
Basically i am not sure how we can persist the errors of formik? Specially in this scenario
There is a way to persist the error into your container's state using an effect like the one documented here: https://github.com/jaredpalmer/formik/issues/1633#issuecomment-520121543
If you create a form listener component that checks Formik's prop for changes and records it to the parent component.
I'd use that component like:
const MyFormWrapper = ({currentIndex}) => {
const [errors, updateErrors] = React.useState([]);
const errorHandler = React.useCallback((newErrors) => updateErrors([
...errors,
[currentIndex]: newErrors
]), [currentIndex, errors]);
return (
<Formik initialState={getInitialState(currentIndex)} initialErrors={errors[currentIndex]}>
// ...
<ErrorListener onChange={errorHandler} />
</Formik>
)
}
(I believe initialErrors is implemented in v2 (I could be wrong or it could not be merged yet). If not or you're using v1, you'll have to show error messages with formikProps.errors.myField || errors[currentIndex].myField && <ErrorMessage />
@anand-neema formik is really not designed to be performant on forms with that many fields or spreadsheet-like UI.
Hey Jared,
Should this be an issue with 50-100 input fields? I am experiencing a laggy input field. Please let me know if this is fixable. I am already using FastField.
Best, Kevin
@kevinvugts there are numerous reasons input can be slow. Once you achieve that many active fields, it's possible Formik would have some slow rendering, depending on many factors including:
I'd recommend trying to create the name number / type of basic fields without third parties or userland code, in a codesandbox and seeing if the issue occurs there. It will also be helpful to run the profiler to make sure that the render time is spent in Formik code / React rendering and not something external. Codesandbox itself may add some overhead to rendering, so reproing in a simple CRA repo might be even better.
Ultimately though, you may find that the large number of fields is problematic. If this is the case, I'd recommend opening a new issue with reproduction, but I'd also suggest considering alternative rendering methods including breaking the form up into smaller parts which are editable, like a single row in a spreadsheet or form-wizard style pagination within formik. It can also be helpful for user experience to break down forms into smaller, digestible pieces, depending on your use case.
Hi Jared, I have several fields in my form and also experience problems with slowness. I also use Material UI so I assume that both libraries together may be less performant. I tried using FastField in my code, but it doesn't help at all. I may be not using it properly.
Here is code sandbox with my problem: https://codesandbox.io/s/ecstatic-microservice-hz3p6?fontsize=14&hidenavigation=1&theme=dark
Fast field seems to rerender even, when other fields are being changed, as you can observe in console.
Regards
Hi Jared, I have several fields in my form and also experience problems with slowness. I also use Material UI so I assume that both libraries together may be less performant. I tried using FastField in my code, but it doesn't help at all. I may be not using it properly.
Here is code sandbox with my problem: https://codesandbox.io/s/ecstatic-microservice-hz3p6?fontsize=14&hidenavigation=1&theme=dark
Fast field seems to rerender even, when other fields are being changed, as you can observe in console.
Regards
I have the exact same issue indeed. How can we solve this @jaredpalmer ?
@kevinvugts there are numerous reasons input can be slow. Once you achieve that many active fields, it's possible Formik would have some slow rendering, depending on many factors including:
- React / Formik versions,
- whether you're using functional or class components,
- if you're minimizing renders (memoization, shouldComponentUpdate) where possible in your userland code,
- if you're performing expensive actions in userland code, and
- if you're using third party inputs or style packages, whether they optimize their own renders
I'd recommend trying to create the name number / type of basic fields without third parties or userland code, in a codesandbox and seeing if the issue occurs there. It will also be helpful to run the profiler to make sure that the render time is spent in Formik code / React rendering and not something external. Codesandbox itself may add some overhead to rendering, so reproing in a simple CRA repo might be even better.
Ultimately though, you may find that the large number of fields is problematic. If this is the case, I'd recommend opening a new issue with reproduction, but I'd also suggest considering alternative rendering methods including breaking the form up into smaller parts which are editable, like a single row in a spreadsheet or form-wizard style pagination within formik. It can also be helpful for user experience to break down forms into smaller, digestible pieces, depending on your use case.
Hi,
Thanks for our extensive reaction this really helps! How would you split up the form into chunks? Right now I have the following code:
Multiform.js https://pastebin.com/4vv3AJtA
Builder.js https://pastebin.com/CPiSxdNb
Could you give it a quick look to check for potential performance issues? Thanks in advance!
Best, Kevin
My current fix is to wrap my custom components that are rendered by the FastField
with either React.memo()
or useMemo()
and memoize it by things that FastField
is supposed to update. You can see example here:
https://codesandbox.io/s/formik-fast-field-hz3p6?fontsize=14&hidenavigation=1&theme=dark
It does help a bit, however it looks like the FastField wasn't working properly.
My current fix is to wrap my custom components that are rendered by the
FastField
with eitherReact.memo()
oruseMemo()
and memoize it by things thatFastField
is supposed to update. You can see example here:https://codesandbox.io/s/formik-fast-field-hz3p6?fontsize=14&hidenavigation=1&theme=dark
It does help a bit, however it looks like the FastField wasn't working properly.
Doesn't solve it for me. Can you have a look into my code (on the top of)what's causing the slow typing?
Doesn't solve it for me. Can you have a look into my code (on the top of)what's causing the slow typing?
Looking at your code I can't tell why it's slow - I don't see how many fields you render. I guess at least several, in my case it's where it starts slowing down. In your code you depend on the FastField to make it more performant, which in my case doesn't help. In my case my custom memoization did help, but not to a point where I am satisfied, but it's because I'm using also FieldArray and a very complex state, which I will try to memoize next and let you know whether it helped.
If you want to check what slows u down, try the React's profiler tool. What I do is starting the profiler, typing just one letter in a text field and then stopping the profiler. Then I investigate the recorder scenario, that's how I came to a conclusion that FastField rerenders its children even when some other field changes.
Doesn't solve it for me. Can you have a look into my code (on the top of)what's causing the slow typing?
Looking at your code I can't tell why it's slow - I don't see how many fields you render. I guess at least several, in my case it's where it starts slowing down. In your code you depend on the FastField to make it more performant, which in my case doesn't help. In my case my custom memoization did help, but not to a point where I am satisfied, but it's because I'm using also FieldArray and a very complex state, which I will try to memoize next and let you know whether it helped.
If you want to check what slows u down, try the React's profiler tool. What I do is starting the profiler, typing just one letter in a text field and then stopping the profiler. Then I investigate the recorder scenario, that's how I came to a conclusion that FastField rerenders its children even when some other field changes.
@wnadurski this is the fields json: https://pastebin.com/Cnb2pJwt
Could it be the map function which is being called over and over again on each render?
I noticed that onchange callback mutate every times any value in form changes, it forces update on all form field included Pure Components
It may be a noob question. Even though how can I use FastField If I use a third part input component like material-ui's TextField
Yeah I'm kind of using many custom components that use hooks useField
, so I'm kind of hoping the useFastField hook #1772 would be implemented soon.. Otherwise big forms are very slow to update. Some of the use cases include multiple form groups with conditional hide and show that makes it very slow to re-render...
Anyone has luck on implementing custom form components without updating the whole forms?
@mdmad
using create react app and semantic ui i built ~40 fields. input is very slow whilst running the app in dev mode. but when i run yarn build and run the app with serve -s build, there is no delay in input fields. can i expect the same results in whilst running on a production server?
This has helped me! With a production build things are much faster!
using create react app and semantic ui i built ~40 fields. input is very slow whilst running the app in dev mode. but when i run yarn build and run the app with serve -s build, there is no delay in input fields. can i expect the same results in whilst running on a production server?
You saved my day! The production build is a lot better performance!
@mdmad7
using create react app and semantic ui i built ~40 fields. input is very slow whilst running the app in dev mode. but when i run yarn build and run the app with serve -s build, there is no delay in input fields. can i expect the same results in whilst running on a production server?
You saved my Saturday! 😆 Thanks for the hint!
@jaredpalmer
<FastField>
is best used on pure fields that don't impact other fields either by changing another field's value or error message. State is kept locally in FastField and then synced up to the top level<Formik/>
component once onBlur is called.
Why isn't FastField
the default then? 🤔
@peraltafederico because users often need effects triggered on Change and not on Blur. V3 will have the best of both worlds by using subscription slicing to achieve render independence between all components instead of delaying updates. In my opinion this would deprecate FastField, or at least make it an edge case.
@peraltafederico because users often need effects triggered on Change and not on Blur. V3 will have the best of both worlds by using subscription slicing to achieve render independence between all components instead of delaying updates. In my opinion this would deprecate FastField, or at least make it an edge case.
Sounds good!
You can try in formik SetFieldValue('fieldname', value, false) you can set shouldvalidate to false
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
<FastTextField
name={`person[${i}]`}
error={touched && errors}
type="text"
value={item}
className="text-field"
handleChange={(value) =>
formik.setFieldValue(
`person[${i}]`,
value
)
}
/>
};
using create react app and semantic ui i built ~40 fields. input is very slow whilst running the app in dev mode. but when i run yarn build and run the app with serve -s build, there is no delay in input fields. can i expect the same results in whilst running on a production server?
I was just going to re-write my application with ~30 fields before I saw your comment, you saved me from a days work!:medal_military:
@anand-neema formik is really not designed to be performant on forms with that many fields or spreadsheet-like UI.
Straight forward answer, i hope v3 would solve the performance issues
I don't know if this is specific to formik, but I had issues similar to this and one solution was to split my form into separate components and have them conditionally render based on some expandable boolean.
This cuts down renders as long as not all sections open at once. Worked for my use case
I have same issue, I have many fields, splited to many child components. Each child I pass below props from formikProps
<ChildForm bulk={bulk} errors={errors} touched={touched} values={values} setFieldValue={setFieldValue} />
Should I use setFieldValue
?
Use
<FastField />
But it have drawbacks like updating the component's or field
I have a large form with 20~30 fields. It seems formik becomes slow when there are large number of fields. It seems to validate every field on every keystroke. Is there a good way to mitigate this issue?