-
-
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
Render optimization #2749
Render optimization #2749
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/formium/formik/b12x0f7f9 |
Why don't we expose all the stable methods from a single API hook like The API would support useContextSelector nicely I think. |
We can have |
@johnrom you are correct that we can just have |
we tested this PR and it is still rerendering everything so the idea is to rebuild most of the hooks using |
Yeah i didn't implement any of the re-rerendering optimizations yet. |
Size Change: +4.88 kB (10%) Total Size: 45.9 kB
ℹ️ View Unchanged
|
packages/formik/src/Formik.tsx
Outdated
@@ -631,7 +631,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({ | |||
if (!isString(eventOrTextValue)) { | |||
// If we can, persist the event | |||
// @see https://reactjs.org/docs/events.html#event-pooling | |||
if (!!(eventOrTextValue as React.ChangeEvent<any>).persist) { | |||
if ((eventOrTextValue as any).persist) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This confuses me. eventOrTextValue is already string | React.ChangeEvent<any>
, so if !isString(eventOrTextValue)
then eventOrTextValue will automatically be inferred as React.ChangeEvent, which means there shouldn't be a cast here at all. Are we using an old typescript version? Or the wrong definition of isString
which does not use type predicates?
-if ((eventOrTextValue as any).persist) {
+if (eventOrTextValue.persist) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idk this didn’t have anything to do with this PR it just showed up in ts. reality is that the types might be lying (if we are in RN) and also that in react 17 this is a no op anyways.
Hello, happy to help contributing to this PR with your guidance. Please let me know if you need anything ! |
I think we should consider dependent fields if we're going to take this approach. We could add an <Field name="fieldA" />
<Field name="fieldB" include={{ fieldA } => { fieldA }} validate={
(value, dependentFields) => value * dependentFields.fieldA < 100
} /> Then this field's render and field-level validation can be triggered when either fieldA or fieldB changes. |
@johnrom This is a good idea. Any thoughts on whether we should call this StrictField or FastField vs. break Field? |
I keep going back and forth on the API I suggested above. Seems like it could be done with useField and a custom prop. If we went this route, I'd prefer not to branch out into another component like FastField -- we've all seen the fallout of deprecating it. I feel like there should be one Field. I wonder if there is a way we can opt in to the new behavior at build time with a feature flag? This Context Selector business is very cool, but it's likely to be deprecated if the React team ever releases a solution which optimizes these renders via another method. For example, the input lag issue would probably be solved by Concurrent Mode. We may want a way for users to opt into this behavior so long as they need it, and if it ever becomes the default that's great. But if it gets deprecated users should be able to opt into it for the next major version or two instead of having to rewrite their apps. Where we could put a feature flag is a whole different question. Webpack plugin? Formik prop? Apparently I contribute more questions than answers, lol |
🦋 Changeset detectedLatest commit: dce5e8d The changes in this PR will be included in the next version bump. This PR includes no changesetsWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@johnrom Technically speaking, this implements FastField and useFastField correctly. Instead of having to tell people in the fast field example, "don't get other form values from in here!" this just removes them entirely from the render props. I agree it would be nice to have one version of Field, and I think we can get there, but I don't think people want to rewrite their apps. Unfortunately most fields should just work, but obviously some will not. A couple of options,
|
Codemods sound cool if webpack/babel plugin & feature flags are just a crazy idea. I've never looked at how to build them, just thought it would be a modern approach for deprecating commonly used functionality. .Net uses these kinds of flags a lot in the compilation process which allows them to support tons of new functionality while not breaking old code. |
Hey @jaredpalmer, I'm glad you've just finished this feature as I'm building a really huge form in Formik and this is needed a lot, since it's really laggy. Could you tell me roughly when can we expect this change released? |
This begins preparing Formik for concurrent mode.
unstable_useStrictField
andunstable_StrictField
to exports. They actually work likeFastField
and auseFastField
(if it existed). I left FastField as is for now because it's not 1:1 withStrictField
, although one could argue that it really is since state is stale in FastField's render props on other fields. Anyways, we can and need to debate naming and deprecations going forward.handleChange
andhandleBlur
internals once we figure out where things are goingCloses #1007, #450, #945, #2327
Proof of Concept: https://codesandbox.io/s/formik-use-context-selector-2-hso7i?file=/src/App.tsx
Basic custom field
Stays the same
Custom Imperative handler of the same field
Bad (but, how it works today)
Good
Setting the value of another field or other Formik state
Bad
Good