You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There have been several issues now (#2186, #2503, and #2508 at least) mentioning the unexpected behavior with field-levelresolveInput hooks. Essentially, instead of the return value from field-level hooks matching the structure of the resolvedData input, you need to return a specific value resolvedData.name, for example).
I did some digging, and I figured out why this happens. In List._resolveInput, there's this block:
// Run the schema-level field hooks, passing in the results from the field// type hooksresolvedData={
...resolvedData,
...(awaitthis._mapToFields(this.fields.filter(field=>field.hooks.resolveInput),field=>field.hooks.resolveInput({ ...args, resolvedData }))),};
The problem with this is, since _mapToFields uses arrayToObject, if the hook here returns an object such as { name: 'newNameValue' }, resolvedData from here on out will end up looking like this:
{name: {name: 'Test8'}}
This happens since arrayToObject returns an object with each field's path as the key, and the value the result of the hook - in this case, an object. If the hook simply returns a value, everything maps as expected.
I'm not sure how best to solve this, but it's definitely unexpected behavior. Couple options:
Keep the current behavior and simply add a doc note explaining you need to return a value from field-level resolveInput hooks. This would conceptually make sense. Since it's a field hook, you're returning the new value for that field.
Make the resolvedData argument for field hooks simply be the value for that hook. This way, the "output should match the structure of the input" design would hold. However, this would mean the resolved data for other fields no longer gets passed in to the field hook, like it currently does - if that's an issue. For example, if you have a field-level hook on a name field in a User list, and change both the name and email fields, the resolvedData input for the hook will be, for instance:
{name: 'Test9',email: 'test@keystone.js.foo'}
Automatically pick the value out of the returned object by field path in the _mapToFields callback above. This could be combined with a check on the returned value's type.
There's also field typeresolveInput hooks to consider. Looking at these, it seems they actually already simply return the value for that field, so changing the behavior for the field level hooks seems reasonable.
🤔
The text was updated successfully, but these errors were encountered:
I might be too close to it but I don't understand the confusion. I had to do this yesterday and I initially made a mistake of returning an object but immediately realised I ended up with something like { name: { name: 'Mike' } } so, I returned the value.
I think the only option is:
"Keep the current behavior and simply add a doc note explaining you need to return a value from field-level resolveInput hooks. This would conceptually make sense. Since it's a field hook, you're returning the new value for that field."
Anything else is a large breaking change to something pretty highly used.
Keystone 5 has officially moved into active maintenance mode as we push towards the next major new version Keystone Next, you can find out more information about this transition here.
In an effort to sustain the project going forward, we're cleaning up and closing old issues such as this one. If you feel this issue is still relevant for Keystone Next, please let us know.
There have been several issues now (#2186, #2503, and #2508 at least) mentioning the unexpected behavior with field-level
resolveInput
hooks. Essentially, instead of the return value from field-level hooks matching the structure of theresolvedData
input, you need to return a specific valueresolvedData.name
, for example).I did some digging, and I figured out why this happens. In
List._resolveInput
, there's this block:The problem with this is, since
_mapToFields
usesarrayToObject
, if the hook here returns an object such as{ name: 'newNameValue' }
,resolvedData
from here on out will end up looking like this:This happens since
arrayToObject
returns an object with each field's path as the key, and the value the result of the hook - in this case, an object. If the hook simply returns a value, everything maps as expected.I'm not sure how best to solve this, but it's definitely unexpected behavior. Couple options:
resolveInput
hooks. This would conceptually make sense. Since it's a field hook, you're returning the new value for that field.resolvedData
argument for field hooks simply be the value for that hook. This way, the "output should match the structure of the input" design would hold. However, this would mean the resolved data for other fields no longer gets passed in to the field hook, like it currently does - if that's an issue. For example, if you have a field-level hook on aname
field in a User list, and change both thename
andemail
fields, theresolvedData
input for the hook will be, for instance:_mapToFields
callback above. This could be combined with a check on the returned value's type.There's also field type
resolveInput
hooks to consider. Looking at these, it seems they actually already simply return the value for that field, so changing the behavior for the field level hooks seems reasonable.🤔
The text was updated successfully, but these errors were encountered: