bug report
const Component = () => {
useField("firstName", { subscription: { value: true }, initialValue: "Max" });
return (
<div>
<label>First Name (new)</label>
<Field
name="firstName"
component="input"
type="text"
placeholder="First Name"
/>
</div>
);
};
When changing the input value of firstName Field to e.g. 'Max abc' and afterwards replacing this Component with an identical ComponentCopy (same fieldName and both using the useField() hook) the changed input.value gets reset to the initialValue: "Max" and therefore looses its changes.

Expected to work like <Form initialValues={{ firstName: "Max" }} ...> (which I added to the Sandbox demo at the bottom). When changing the input value of firstName Field to e.g. 'Max abc' and afterwards replacing this Component with an identical ComponentCopy (same fieldName, both use useField() hook to supply initialValue) the changed input.value (which is still part of the form) gets preserved and ComponentCopy displays the correct input.value 'Max abc' instead of the initialValue: "Max".

firstName demonstrates the bug and lastName presents a hacky solution to get the expected behavior.
At the bottom a standalone form demonstrates the expected behaviour by supplying the initialValues to the <Form .. directly which is at the moment not achievable by using the useField() hook.
https://codesandbox.io/s/react-final-form-simple-example-dmh3h?fontsize=14
"final-form": "4.14.1",
"react-final-form": "6.2.0",
"node": ">=10.16.0",
_fyi_ I have cleaned up the Sandbox example, updated the bug report and added improved gifs.
What u are asking here would make the code slightly more complicated than it needs to be. I would advise just using initialValues on the entire form - that way with initialValues values can be treated as preserved when changing rendering components OR when dealing with conditionally rendered components. And initialValue on the field itself might be treated as resetting the field. Both use cases are actually OK and both should be (somehow) supported.
Thank you, @Andarist, for your quick reply. What we try to achieve is a little bit more complicated.
initialValue), whose values the user may later on change.tl;dr use case: add, on the fly, new fields (with initial values) to the form which later on may be changing rendering components.
As far as I have browsed the documentation, I was not able to find a trivial way to add new initial values to the initialValues object on the fly.
I tried to manipulate the initialValues object in the following manner [1], but it causes first off unnecessary rerendering, as well as resets the field which was initially set in the advised way by supplying its initialValue to initialValues.
That was my motivation to open this issue, because, in my opinion, should the useField() hook provide a non-resetting initialValue experience as does the initialValues while changing rendering components.
[1] https://codesandbox.io/s/react-final-form-simple-example-3b98e?fontsize=14

IMHO, in that case, you could just not render different component which controls the same named value, but rather just use useField inside a single component which in turn would render different component based on your conditions and returned field state.
I'm ofc not aware of your all constraints, so please describe the situation in more detail if you think that's not a suitable solution.
@Andarist most certainly this approach would be easy to accomplish. But the project does indeed have some constraints which don't allow us to implement it that way. Let me explain them.
We are not able to use useField() to set the initialValue inside a single component, because of the reordering of the row elements, as well as combining and unlinking of certain fields is possible and thus change rendering components is needed. Setting initialValues on the Form element is not possible as well, as we don't know which fields the user creates in the process.
I hope I was able to explain our constraints somewhat clearly.
You have explained the problem really well! I feel like this could be supported - but I'm going to leave that decision up to @erikras .
By stretching a little bit current APIs I've managed to prepare a working solution for you though - https://codesandbox.io/s/react-final-form-simple-example-g9gqf - which can be used as an intermediate workaround.
I got the similar problem but with destroy on unregister https://github.com/final-form/react-final-form/issues/523
With two fields it's harder to stop this issue but it's more visible with enabled destroy on unregister property. I quickly looked through code and found that to get initial value for for field you need to registerField and then immediately do unregister
// useField.js
import React from 'react';
import { useField as _useField, useForm } from 'react-final-form';
export const useField = (name, config) => {
const form = useForm();
const [alreadyRegistered] = React.useState(
() => form.getFieldState(name) !== undefined,
);
if (alreadyRegistered) {
// eslint-disable-next-line no-unused-vars
let initialValue;
// eslint-disable-next-line prefer-const, no-param-reassign
({ initialValue, ...config } = config);
}
return _useField(name, config);
};
// LabelEditor.js
import { useField } from './useField';
// ...
const { input } = useField(`${element.id}.label`, {
type: 'text',
subscription: { value: true },
initialValue: get(element, 'state.label'),
});
@Andarist thank you for your solution! I have tested it with our setup, and for now, it suffices as an intermediate workaround.
Nevertheless, I believe that fixing this issue at the useField() level as well as <Field .. level #536 would improve and simplify the UX of this remarkable form library.
Fix published in [email protected].
Most helpful comment
@Andarist thank you for your solution! I have tested it with our setup, and for now, it suffices as an intermediate workaround.
Nevertheless, I believe that fixing this issue at the
useField()level as well as<Field ..level #536 would improve and simplify the UX of this remarkable form library.