#3548320 Flicker free prop linking
Closes #3548320
There are two significant aspects to making this work:
formStateToStore
to not use stale data
Refactor the props form's When a value changes in the props form, it (after the debounce delay) reaches formStateToStore
,
where we update our stores and make the necessary API requests.
In order to debounce a function defined in a React component, it needs to be made persistent - usually with useCallback
or useRef
.
In HEAD, formStateToStore
took one argument: newFormState
.
The logic in formStateToStore
also depends greatly on the inputAndUiData
variable, which is defined one scope level up.
After an input is linked, the other inputs still had the useCallback
-wrapped formStateToStore
they were initially sent, which includes stale inputAndUiData
. We address the stale inputAndUiData
problem by simply making that an argument passed into the function, so it's always working with the current data. This made the formStateToStore
implementations for Component & Page data different enough that I moved the debounce implmentation out of the shared inputBehaviors
and into the form specific InputBehaviorsComponentPropsForm
and InputBehaviorsEntityForm
Create an action specific to prop linking
Prop linking is technically a programmatic update - we are changing the value of a prop but it's not by interacting with it's corresponding form input (i.e. the linking of a text field is not done by interacting with that text input)
There is an updateExistingComponentValues
action that deselects a component before updating the values, then reselects it after the update. This is what causes the flicker. This was not as big a problem for other uses because it's typically invoked from elsewhere in the UI.
I created a dedicated updateExistingComponentValuesForLinking
that is very similar, but does not deselect/reselect and instead invokes additional actions to match the sequence of events that would occur during a form interaction. I tested to see if this could work with non-prop-linking scenarios and that was less successful - hence the separate updateExistingComponentValues
and updateExistingComponentValuesForLinking
. See the @todo
in the code for more info