The form.restart() in my reset button resets all fields states and values as per my understanding of this Final-Form. The method fires and resets all fields in my form and I can capture the event in the autocomplete, but I am unable to capture the clear event in the textfield - I have a state (not related to the value of the field) I need tor reset.
My form reset button
<Button
type={"button"}
disabled={submitting || pristine}
variant={"outlined"}
onClick={() => {
form.getRegisteredFields().forEach((field) => form.resetFieldState(field));
form.restart();
if (clearActionHandler) {
clearActionHandler();
}
setFormSubmittedOnce(false);
}}
>
Clear
</Button>;
My textfieldadapter
const [shrink, setShrink] = useState < boolean > false;
const countCharacters: (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => boolean = (e) => {
setCount(e.target.value.length);
return maxCharacterCount === 0 || e.target.value.length < maxCharacterCount;
};
return (
<TextField
{...input}
{...rest}
onChange={(e) => {
if (countCharacters(e)) {
input.onChange(e);
}
}}
value={input.value}
onBlur={(e) => {
!input.value && input.onBlur(e);
!input.value && setShrink(false);
}}
error={meta.error && meta.touched}
helperText={
meta.touched ? (
<React.Fragment>
{maxCharacterCount > 0 ? (
<React.Fragment>
<Typography variant={"body1"} textAlign={"end"}>
{count}/{maxCharacterCount}
</Typography>
<br />
</React.Fragment>
) : null}{" "}
{meta.error}
</React.Fragment>
) : maxCharacterCount > 0 ? (
<React.Fragment>
<Typography variant={"body1"} textAlign={"end"}>
{count}/{maxCharacterCount}
</Typography>
<br />
</React.Fragment>
) : (
""
)
}
placeholder={placeholder}
fullWidth={true}
margin={"dense"}
multiline={multiline > 1}
rows={multiline}
inputProps={inputProps}
InputProps={{
startAdornment: (
<InputAdornment position={"start"} sx={{ width: "24px" }}>
{startAdornment}
</InputAdornment>
),
}}
InputLabelProps={{
shrink: shrink,
}}
onFocus={() => setShrink(true)}
sx={{
"& .MuiInputLabel-root:not(.MuiInputLabel-shrink)": {
transform: "translate(50px, 17px)",
},
}}
/>
);
Versions of packages: "@mui/material": "^5.11.1", "react": "^18.2.0", "react-final-form": "^6.5.9"
I have tried to capture the onChange event with bluring all elements before the reset method is called, that doesn't call the textfield onblur method. I am just not sure how to clear it away.
Make sure that the field in question has an entry in
initialValuesand that that entry is initialised to an empty string. This is a long shot, so take everything I say as theory, but it looks like what would happen if the initial value was not defined or was explicitly set toundefined.That would mean when you reset the form, the
valueprop of theTextFieldwould be set toundefined. This is not a valid controlled value of aTextField, so the behavior of MUI could well be to switch to uncontrolled mode, where the value is kept internally and not actually controlled by thevalueprop any more. It depends on the library what happens next as this is generally unexpected and leads to non-deterministic behavior, but it's likely that MUI just keeps the previous controlled value around internally, or it's sitting in a transient DOM state on the element itself sincevalueis judged to be no longer the source of truth and so it was never written to the actual DOM element. When the user types again,onChangewould be called, the state in your form set to a string, and it would become controlled again. Base react<input>gives warnings in the console when you transition like this but MUI might not.This might explain why it does not capture the transition to the original form state.
Note
nullis usually not allowed either but there's some final form magic that protects you from that one.I verified MUI does this on a codesandbox (excuse the old class style I just used an old
TextFieldsandbox to build on). If my long shot is correct, the problem is more related to a core issue between your state consistency and the mui lib and less about final form.The fix would be to make sure the field has an entry in
initialValuesset to a string. You could optionally put in guards to check forundefinedand use''instead when that's the case.Take note that
''is actually still falsey so!input.valuewould evaluate to true when it's empty string still. Not sure you care, but something to keep in mind.