Skip to content

Editors' changes overwrite other sections when reordering typed list items #7956

Description

@Jamesg487

Describe the bug

When using a list widget configured with types, reordering the list items via drag-and-drop breaks the data connection for any markdown widgets inside those items.

If the markdown widgets have the same name, i.e. two instances of the same object, the state bleeds between the two. If the objects have different names but both contain markdown fields. The bug report CMS config examples allow you to test both the freeze and state bleed issues. I have included videos of both in action.

In some cases, the editor pane correctly updates the underlying file. The user must save and reload to restore the live preview.

Note: I have explicitly added a unique id field that gets used as the React key for each block to ensure the issue does not lie with simply missing unique keys. The bug persists even with stable keys.

To Reproduce

  1. Create a list widget in config.yml that uses two variable types.
  2. Inside both of those types, include a markdown widget.
  3. Create a custom preview template and render the markdown widgets.
  4. In the CMS editor, add two list items.
  5. Drag and drop the list items to swap their order.
  6. Attempt to type inside a markdown widget in the editor pane.

Expected behavior

After reordering typed list elements, the markdown fields within continue to render the correct contents in the preview.

Screenshots

Freeze

Screen.Recording.2026-08-10.at.14.36.38.mov

State bleed

Screen.Recording.2026-08-10.at.14.09.32.mov

Applicable Versions:

  • Decap CMS version: 3.1.2
  • Git provider: GitHub
  • OS: MacOS 26.6
  • Browser version: Chrome - 151.0.7922.109

CMS configuration

collections:
  - name: "pages"
    label: "Pages"
    folder: "content/pages"
    create: true
    fields:
      - name: "title"
        widget: "string"
      - name: "sections"
        label: "Sections"
        widget: "list"
        types:
          - label: "Text Block 1"
            name: "text_block_1"
            widget: "object"
            fields:
              - { name: "id", widget: "string" }
              - { name: "content_one", widget: "markdown" }

          - label: "Text Block 2"
            name: "text_block_2"
            widget: "object"
            fields:
              - { name: "id", widget: "string" }
              - { name: "content_two", widget: "markdown" }

Additional context

Preview

const PagePreview = ({ widgetsFor }) => {
  const sections = widgetsFor('sections');
  
  if (!sections || !sections.size) return null;

  return (
    <div>
      {sections.map((section, index) => {

        if (!section) return null;

        const uniqueId = section.getIn(['data', 'id']);
        const reactKey = uniqueId || index;
        const blockType = section.getIn(['data', 'type']);
        
        let markdownWidget = null;
        if (blockType === 'text_block_1') {
          markdownWidget = section.getIn(['widgets', 'content_one']);
        } else if (blockType === 'text_block_2') {
          markdownWidget = section.getIn(['widgets', 'content_two']);
        }

        return (
          <div key={reactKey} style={{ border: '2px solid #333', padding: '15px', marginBottom: '10px' }}>
            <h4>Type: {blockType} | Key: {reactKey}</h4>
            
            {markdownWidget}
            
          </div>
        );
      }).toArray()}
    </div>
  );
};

CMS.registerPreviewTemplate('pages', PagePreview);

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugcode to address defects in shipped code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions