Knowledge Drop

Looker Extension Framework Development - Edge Case Quirks


Userlevel 4

Last tested: Mar 23, 2021
 

Just a brain dump of stuff I found while tinkering with the Extension Framework.

Firebase

If you want to sync stuff with a realtime database, Firebase is a good option but you will have to do something like this in your main App component to get a bi-directional sync

  useEffect(() => {

      firebase.database().ref(`profservices/fishes`).on('value', snapshot => {

          if (snapshot.val()) setFishes(snapshot.val())

      })

  }, []);

  useEffect(() => {

      firebase.database().ref(`profservices/fishes`).update(fishes)

   }, [fishes])

 

You can try using re-base, but I couldn’t get it to sync from Firebase as well as write to. There is an open source firebase react library with built hooks, but I haven’t used it.

This actually works incredibly well and is something to consider for things like annotations, comments etc.

 

Babel

Babel will produce this weird error whenever you try to run any async/await functions;

regeneratorRuntime is not defined

To fix this, change the babel.rc file to include a target to node10. Example:

{

  "presets": [

    [

      "@babel/preset-env",

      {

        "targets": {

          "node": "10"

        }

      }

    ],

    "@babel/preset-react"

  ],

  "plugins": [

    "@babel/plugin-proposal-class-properties"

  ]

}


Webpack

If you’ve built an app outside of Extensions and have some nice CSS you want to retain, webpack needs to be given a rule to import CSS, the syntax for which is different depending on whether you’re using WP 4 or WP 5:

Inside the module rules, use this:

module: {

 

  rules: [

    {

      test: /\.(js|jsx)$/,

      exclude: /node_modules/,

      use: {

        loader: "babel-loader"

      }

    },

    {

      test: /\.css$/i,

      use: ["style-loader", "css-loader"],

    },

    {

      test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,

      loader: "url-loader",

      options: {

        limit: 8192,

      },

    }

   

  ]

},

You may need to npm install style-loader and css-loader first but just doing npm install in the root of your app should handle this anyway.

Extension Provider

The <ExtensionProvider/> component should be nearest the root of the component tree, which outside of an Extension, you may not have a single root ‘node’. As a result, what I saw was this error when I put it in both nodes:

Error: Failed to establish communication with Looker host

   at eval (connect_extension_host.js?748f:20)

 

Create a parent component that renders both and call that from index.js instead. This is probably best practice for React anyway, I don’t know, don’t @ me about this.

Extensions not connecting

Similar to above but for different reason, and more generic. You might just get an error saying that the Extension wasn’t initialized at all, which is ambiguous but really just means there’s something that’s trying to load that is broken in the app. Most of the time I just traced down through the component tree disabling stuff until it worked and tracing back to figure out what went wrong.

Sometimes the problem can be that what you’ve provided to <ExtensionProvider> is bad and it breaks at a point in a big block of code that’s hard to deduce. 9 times out of 10 it’s your fault.

Local Storage

If you’re building in React, outside of Extensions accessing browser localStorage is easy but we don’t call it out in the extension-sdk-react package documents so it’s not clear. It’s shown in our regular extension sdk docs, but it’s unclear about whether there’s a react-specific method.

I did this:

const context = useContext(ExtensionContext)

  const sdk = context.core40SDK

  const localStorageSet = async () => {

      try {

        await context.extensionSDK.localStorageSetItem('testbed', 'blah')

      } catch (error) {

        console.error(error)

      }

    }

  useEffect(() => {

      localStorageSet()

  })

 

More to come...

 

This content is subject to limited support.                

 

 


0 replies

Be the first to reply!

Reply