payloadcms / payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
https://payloadcms.com
MIT License
23.44k stars 1.49k forks source link

JSON fields don't show updated value after useField setValue #4575

Closed jschuur closed 8 months ago

jschuur commented 9 months ago

Link to reproduction

No response

Describe the Bug

I've created a ui Field with a custom component that's a button to update the contents of a json Field (this is a prototype, eventually, this would fetch data from a Google Sheet).

However, when I click the custom button to trigger a setValue from useField for the JSON field, the Monaco editor component that Payload uses doesn't seem to refresh to reflect the new value.

To Reproduce

Create a collection...

import { CollectionConfig } from 'payload/types';

import SyncButton from '../components/SyncButton';

const defaultSurveyContent = { foo: 123};

export const Surveys: CollectionConfig = {
  slug: 'surveys',
  fields: [
    {
      name: 'name',
      type: 'text',
      required: true,
    },
    {
      name: 'slug',
      type: 'text',
      required: true,
      unique: true,
    },
    {
      name: 'content',
      type: 'json',
      defaultValue: defaultSurveyContent,
    },
    {
      name: 'syncButton',
      type: 'ui',
      admin: {
        components: {
          Field: SyncButton,
        },
      },
    },
  ],
};

...with the following custom UI component:

import { Button } from 'payload/components';
import { useField } from 'payload/components/forms';
import React from 'react';

export default function SyncButton() {
  const { value: content, setValue: setContent } = useField<string>({ path: 'content' });

  function syncContent() {
    setContent({ foo: 'bar' });
  }

  return (
    <Button onClick={syncContent} buttonStyle='secondary'>
      Sync Content
    </Button>
  );
}

Click the 'Sync content' UI field and the JSON data in the Monaco editor component doesn't change. But if you save the record and reload the page, the JSON value is now { "foo": "bar" }, suggesting the click changed it, but the component just didn't re-render.

This works fine if you use setValue on a text field, so this issue seems to be specific to the Monaco editor.

Payload Version

2.5.0

Adapters and Plugins

No response

jschuur commented 9 months ago

Based on this issue, I thought this could be solved by passing in the formatOnType and formatOnPaste editorOptions to Monaco, but that didn't seem to help.

I did first have to patch 2.5.0 to allow me to set editorOptions for JSON fields (PR pending: https://github.com/payloadcms/payload/pull/4574).

JessChowdhury commented 8 months ago

Hey @jschuur, thanks for opening the PR to add editorOptions to the JSON field schema.

I tested the formatOnType and formatOnPaste props and it did not seem to refresh the code editor as you would expect. There might be another prop that is useful, I will take a further look and get back to you.

EDIT: I found the issue that was preventing the Monaco editor from reflecting the updated JSON, it will be fixed once we merge this PR and make the next release!

github-actions[bot] commented 2 weeks ago

This issue has been automatically locked. Please open a new issue if this issue persists with any additional detail.