javascriptreactjsnetlifynetlify-cms

TypeError: Cannot read property 'map' of undefined on Netlify CMS/React.js


Environment

Explanation

As you can see below, the code works for the most part, but specifically in the CMS's Preview pane, when I add a group element (list), it breaks for some reason. I've noticed that this issue happens in the custom preview template, in this line, but I wasn't able to see anything wrong in there. Is there a possible fix to it?

When adding a group element enter image description here

When adding a subgroup element (nested list) - it works as expected enter image description here

Code

I created this public repo with just the code needed, so anyone can easily reproduce. You can also see this site here.

config.yml

publish_mode: simple
slug:
  encoding: unicode
  clean_accents: false
  sanitize_replacement: "-"
backend:
  name: git-gateway
  branch: master
media_folder: static/images
public_folder: /images
collections:
  - name: pages
    label: Pages
    files:
      - file: src/pages/index.md
        label: Index
        name: index
        fields:
          - label: Groups
            name: groups
            widget: list
            fields:
              - label: Title
                name: title
                widget: string
              - label: Subgroups
                name: subgroups
                widget: list
                fields:
                  - label: Subtitle
                    name: subtitle
                    widget: string
    publish: true
    sortableFields:
      - commit_date
      - commit_author
    view_filters: []

Solution

  • The map is failing when you add a new Group because the subgroup field is undefined.

    For these kinds of issues with custom previews for netlify-cms, you have two options:

    1. Add a default field on the subgroup widget in your config.yml (see here).

    2. Or you can validate and/or fix the input groups object in IndexPagePreview.js before passing it through as a prop to your custom IndexPagePreview: groups.forEach(g => g.subgroup = g.subgroup || [])

    Try them both, one might work better than the other for what you're doing with the data afterwards. :)


    Update:

    So I cloned your code, set up netlify etc etc. so I could get an exact solution working for your data-types.

    Solution 1: See the two new default keys below. If netlify CMS is given these, then it knows how to create the sub-objects for the list widget when you click on new. Otherwise it just goes for an empty string, which is normally fine, but as your preview was mapping sub-fields, it wasn't happy with this.

     fields:
     - {
        label: Groups,
        name: groups,
        widget: list,
        fields:
          [
            { label: Title, name: title, widget: string, default: ''},
            {
              label: Subgroups,
              name: subgroups,
              widget: list,
              default: [{ subtitle: '' }],
              fields:
                [{ label: Subtitle, name: subtitle, widget: string }],
            },
          ],
      }
    
    

    Solution 2: You need to instantiate the entire sub-object if it is empty, so it needs to be this just before you pass it in to the props.

    groups.forEach(g => g.subgroups = g.subgroups || [{subtitle:''}])
    

    After looking closer, doing it the "proper" way (Solution 1) seems better, as the CMS is actually creating the objects in a better way, and will save the objects in a properly-formatted way also. Solution 2 just fixes up the objects for the previewer, it doesn't have any effect on the saved files.