Undistraction/gatsby-plugin-node-fields

Not seeing values from gatsby-source-wordpress transformed

ventinus opened this issue · 3 comments

Hi,

I'm having difficulty getting optional fields from wordpress transformed into the same type of value across the board. Wordpress, unfortunately, gives the default value of false for optional fields if left empty, which causes issues for non-boolean values for the same field, in my case, video.

I've set up the custom content type hero in wordpress using the Pods plugin, which has the video field. I've tried various combinations of predicates to select the right nodes and different approaches with using transformer and/or defaultValue but not seeing any values change out the other end. I've configured it through the gatsby-config.js and gatsby-node.js files with the same results. I see that the predicate is working and I see the false value coming through at that point, so my thinking is that I'm selecting the incorrect node to transform.

This is my plugin setup, which is the last plugin in gatsby-config

    {
      resolve: 'gatsby-plugin-node-fields',
      options: {
        descriptors: [
          {
            predicate: node => node.type === 'hero',
            fields: [
              {
                name: 'video',
                defaultValue: {guid: {defaultVal: ''}},
                transformer: value => {
                  return value || {guid: {}}
                } 
              }
            ]
          }
        ]
      }
    }

And this is the GraphQL warning I get in the console:

warning There are conflicting field types in your data. GraphQL schema will omit those fields.
wordpress__wp_hero.video:
 - type: boolean
   value: false
 - type: object

Note, I've also tried my predicate as predicate: node => node.internal.type === 'wordpress__wp_hero' to the same result.

I'm on the latest node-fields version (0.0.6) and gatsby 1.9.247

Thanks!

@ventinus Thanks for your report. This actually draws attention to the check I'm using to decide whether to use a default value which is a crude negation: !value. I should actually be using isUndefined(value) because false should not be replaced by a default value. I've just published 1.0.0 which will only use a defaultValue if the existing value is undefined.

As for your specific use-case, I'm a little confused by what you are trying to achieve. Wordpress adds fields directly to the node and this plugin adds fields to the node's fields field. Gatsby treats values as immutable, so you don't overwrite a value that already exists, even if it is false. you need to create a new value on fields to use instead. In your case it looks like you are trying to supply a default value for hero nodes that have a video prop that has a value of false. So given that node.video will either be an object with a guid attribute: { guid: 'XXXXXX' } or false, you need to create a new attribute on the node's fields called video with a value of either the existing objects, or your default object if the value is false. You will then need to query fields__video` to get that value out again.

Hopefully the following will work:

  1. You should upgrade to 1.0.0
  2. Remove the defaultValue in your descriptor as this won't be applied given that your values will always be an object or false but never undefined.
  3. Your transformer function:
const isFalse = value => value === false
const DEFAULT_VIDEO_VALUE = { guid: 'XXXXX' }
...
transformer: value =>  {
  return isFalse(value) ? DEFAULT_VIDEO_VALUE : value
}
  1. When you want to access the value query on node.fields.video

Thank you for the reply @Undistraction! I didn't realize that the data was being treated as immutable and do see the fields being transformed under a new fields field for that content type.

Thank you for your work on this plugin, it has been very helpful!

@ventinus You are most welcome. I think they should make it clearer in the docs as it is an important thing to understand. I've actually taken to using fields to effectively define the API that my components will use. I use this plugin to map any values I'll need in my views from wherever they are on the node to a field on fields, and I've found this to be a really helpful approach. This way you don't need to worry about where on the node your values are going to be–they'll aways be in node.fields–which allows your component code to be much simpler and more predictable.

I'm going to go ahead and close this issue. If you have any more questions feel free to ask them in separate issues.