Skip to content

More portable data payload #255

Open
@chrisvxd

Description

@chrisvxd

Problem

The current data model is hard to reason about, which makes it less portable and harder to build custom renderers on top of. Some concerns:

  • zones are weird
  • The Root component is treated differently to the other components
  • DropZones rely on context or render props, which are React-only paradigms, making it hard to implement Multi-framework support #302 and negatively impacting performance

Example of a custom renderers:

  • XML string (i.e. to produce React code)
  • Non-React outputs

Current data model

{
  "content": [
    {
      "type": "Columns",
      "props": {
        "id": "Columns-1234"
      }
    }
  ],
  "root": { "props": { "title": "Page" } },
  "zones": {
    "Columns-1234:left": [
      {
        "type": "Heading",
        "props": { "title": "Hello, world" }
      }
    ]
  }
}

Proposal

react-from-json implements a predictable AST based on, but not tied to, the React tree. It would allow for custom renders and increased portability.

Proposed data model

{ 
  "root": {
    "type": "Root",
    "props": {
      "title": "Page",
      "children": [
        {
          "type": "Columns",
          "props": {
            "left": [
              {
                "type": "Heading",
                "props": { "title": "Hello, world" }
              }
            ]
          }
        }
      ]
    }
  },
  "content": [], // Deprecated, but still supported
  "zones": {}, // Part of DropZone API which will be deprecated, but still supported
}

New slot API

The children prop in the above will be powered by the slot field API, which implements a DropZone-like API but as a field. This makes data much more portable, as it's part of the same payload, whilst also taking advantage of the numerous field APIs (defaultProps, resolveData, etc).

Current proposal:

const config = {
  fields: {
    leftColumn: { type: "slot" }
  },
  defaultProps: {
    leftColumn: {} // Unlike DropZones, you can set defaultProps for slots
  },
  render: ({ leftColumn }) => (
    <div>{leftColumn()}</div>
  )
}

DropZone's will be deprecated but retained to avoid breaking changes, but user's will be directed to the slot API instead.

Considerations

  • Implement migration using migrate() API
  • Consider how content will be deprecated. We could 1) retain content as is indefinitely, 2) retain support for the user's existing payload (i.e. if content is passed in, content will be passed out until the user migrates the data using migrate()), or 3) force the user to migrate() their data (breaking change).
  • Plugins modifying the Data payload will not immediately support slots or content if moved under root.props. Plugins are experimental, so no mitigation necessary.
  • Consider making the react-from-json model a portable standard
  • Consider how we might solve for detached roots, such as in Rendering Puck components outside of DropZone #196

Blockers

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions