T
TanStack12mo ago
genetic-orange

Dirty since last submit

Howdy! After a sidequest at work, I'm back to the migration from React Final Form (RFF) to TS Form. It's going well (although the draft PR with the field wrapper example would be great, so I can make use of DeepKeyValue and all that), but I've got a new roadblock. RFF keeps track of the dirty state as a whole, but also since the last submit (dirty and dirtySinceLastSubmit), which is an absolute necessity for our saving indicator that gets used for our autosaving forms. I tried to convert our saving indicator, but it's not possible without some way of identifying whether a field is modified. isSubmitted and isDirty don't get cleared once the field becomes dirty again. The only difference between my TS Form indicator and my RFF indicator is the field meta used. Here's my mapping from RFF to TS Form - field.meta.modified -> field.meta.isDirty - field.meta.submitFailed -> field.meta.errorMap.onSubmit - field.meta.submitting -> form.store.isSubmitting - field.meta.dirtySinceLastSubmit -> form.store.isSubmitted
import type { FieldMeta, /* ... */ } from "@tanstack/react-form";
// ...

import { Check } from "lucide-react";
// ...
import style from "./FieldInfo.module.scss";

// ...

type SavingIndicatorProps = {
meta: FieldMeta;

/* These two are obtained with `useStore` */
isSubmitting: boolean;
isSubmitted: boolean;
}
const SavingIndicator = (props: SavingIndicatorProps) => {
const { meta, isSubmitting, isSubmitted } = props;

if (!meta.isDirty) return null;

let indicator = null;
if (meta.errorMap.onSubmit) indicator = "Did not save.";
if (isSubmitting) indicator = <span>Saving...</span>;
if (!isSubmitted) {
indicator = (
<span className={style.saved}>
Saved. <Check />
</span>
);
}

return <p className={style.savingIndicator}>{indicator}</p>;
};
import type { FieldMeta, /* ... */ } from "@tanstack/react-form";
// ...

import { Check } from "lucide-react";
// ...
import style from "./FieldInfo.module.scss";

// ...

type SavingIndicatorProps = {
meta: FieldMeta;

/* These two are obtained with `useStore` */
isSubmitting: boolean;
isSubmitted: boolean;
}
const SavingIndicator = (props: SavingIndicatorProps) => {
const { meta, isSubmitting, isSubmitted } = props;

if (!meta.isDirty) return null;

let indicator = null;
if (meta.errorMap.onSubmit) indicator = "Did not save.";
if (isSubmitting) indicator = <span>Saving...</span>;
if (!isSubmitted) {
indicator = (
<span className={style.saved}>
Saved. <Check />
</span>
);
}

return <p className={style.savingIndicator}>{indicator}</p>;
};
My question is: is there any scope for dirtySinceLastSubmit in TS Form?
2 Replies
genetic-orange
genetic-orangeOP12mo ago
For reference, here's a excalidraw diagram of the interaction flow
No description
genetic-orange
genetic-orangeOP12mo ago
It appears I'm not the sharpest tool in the shed. RFF field.meta.modified can be replicated with the following 2 lines
const modifiedRef = useRef(false);
if (meta.isDirty && !modifiedRef.current) modifiedRef.current = true;
const modifiedRef = useRef(false);
if (meta.isDirty && !modifiedRef.current) modifiedRef.current = true;

Did you find this page helpful?