formValues in Plugin context object triggers updates for all objects

Describe the issue:

  • I have a plugin that is leveraging multiple properties of the ctx object.
  • It appears that any change to formValues also seems to result in some of the static data changing as well
  • I’m curious if this is expected.

(Optional) Do you have any sample code you can provide?

This is a snippet from the start of the field extension plugin

export default function MyFieldExtension({ ctx }: PropTypes) {

  const {
    environment,
    plugin,
    itemType,
    currentUserAccessToken,
    formValues,
    fields,
  } = ctx;

  useEffect(() => console.log("Fields changed", fields), [fields]);

...

Each time i edit text in a field I’d expect formValues to change, but this seems to also trigger a change in fields.

Hmm… that is strange. The before/after looks identical. Might be a memoization/diffing bug? Question for @s.verna here…

Is it causing any issues for you in particular?

Actually, this might just be standard React behavior…?

Per the docs, useEffect() uses Object.is comparison, which compares objects by reference and not value =/

e.g.

    const [nestedObject, setNestedObject] = useState({emptyObject: {}})
    const handleButtonClick = () => {
        setNestedObject({emptyObject: {}})
    }

    useEffect(() => console.log("Child changed", nestedObject.emptyObject), [nestedObject.emptyObject]);

Will trigger the useEffect every single time, even though {emptyObject:{}} is the same value every time, because it’s technically a new object, even though both are {}. There might be a way to store the old value as a ref and diff it though, if you really need to…? What are you trying to do with the fields?

Yes, it’s standard React, plus the fact that data from CMS to plugin passes through an iframe so it cannot be equal by reference.

I suggest you using hooks like this one:

It’s like React’s useEffect hook, except using deep comparison on the inputs, not reference equality!

1 Like

Yeah, this is what I understood was standard react behavior, but in this case I was wondering if there was a way that the reference could avoid changing. While that behavior is standard, what isn’t typical in react is that you’d have the reference constantly changing. It sounds like this is a consequence of the iframe.

It might be worth mentioning in the docs somewhere when introducing the context object or something like that.

Thanks for the suggestion. This was the path I was going to go down, but felt if you don’t have to do a deep comparison, you wouldn’t want to. I didn’t realize the iframe was part of the cause of this and wanted to be sure it wasn’t an oversight in how the objects were being created/updated.

Done, thanks for the suggestion!

https://www.datocms.com/docs/plugin-sdk/field-extensions#side-note-ctx-updates-and-react-useeffect