Accessing the Qlik Engine API From React Using Qlik Hooks

John Bellizzi
The Startup
Published in
6 min readOct 6, 2020

Most React developers are familiar with React Hooks which has been around for a couple years now. If you’re not, definitely check out how they work here.

When I first met React Hooks, I fell in love. When our team builds applications that are driven by the Qlik engine, we need a way to handle the varying states of requests and responses from the API. If I want to display data from a hypercube in a chart, I need to request the data using GetLayout(). If I want to request the layout of the hypercube, I first need to create the hypercube and wait until the engine gives me the handle of the new object I created. If I want to create a new object, I need to wait until I’ve opened the app. If I… ok i think you get the point.

This isn’t a new problem really. We’ve always had to handle asynchronous dependencies when working with the engine API. Typically this means using JavaScript promises returned from Enigma.js, or Observables from RxQ. But React Hooks make defining and using connections to the engine easier.

Connecting to the engine

Before continuing, set up a React sandbox to test in using create react app, and also install qlik-hooks

npm install --save qlik-hooks

We’ll run all these examples in App.js.

Define a config object that will connect to a Qlik Sense engine (I’m using the Qlik demo site)

Now import the useConnectEngine hook from qlik-hooks and pass the config object in to it

You will first see engine returned with loading: true and handle: null. Then, if the connection is made successfully, loading will be false and handle will have a Global handle defined.

Making an API call

Now that we have a connection, let’s see how we can actually send an api request to get the version of the engine we are working with.

After we import useEngineVersion from the Global directory of qlik-hooks, we can use it by passing in 2 parameters. The first parameter is the object that contains the handle we are running the method on. In this case, it’s the engine object we defined above. The second parameter is an object that contains a property params that will have all the arguments passed into the EngineVersion API method (in this case, there are no arguments needed so we pass an empty array).

For the first few renders, engineVersion.qResponse will be null while the engine is still connecting and the client is waiting for a response from the EngineVersion method. If it returns successfully, you will end up with a qResponse object containing the information requested from Qlik Sense.

So what’s so special about this? On its own, this isn’t really anything groundbreaking. We’re already able to get data with other Qlik Engine libraries.

The main benefit here is how React can be leveraged using this new Hook model. Whenever the state within a React component function updates, the component will rerender. So instead of having to listen for a valid response from EngineVersion, we can just tell React to use engineVersion.qResponse if it exists, or ignore it until it is not null

No need to handle calling a render function on your own. When the state of engineVersion updates, the component will automatically rerender, and if engineVersion has a qResponse, we’ll display the information in the app.

Opening an app

Let’s take this one step further and display some properties from a Qlik app on our site

We can open an application using the useOpenDoc hook and passing the app id into the params array property. Then, we can pass the app object into useGetAppProperties to get information about the app. Finally, we use the response in appProps to render information on our site.

What’s nice about Qlik Hooks is I don’t have to worry about waiting for a handle response from the OpenDoc method before I call GetAppProperties. I just set up the hook calls and Qlik Hooks internally will do the async handling for you.

Getting into Hook trouble

Before we continue with more examples, I want to explain some rules for React Hooks that also apply to Qlik Hooks. Mainly, hooks can not be called from inside loops, conditions, or nested functions. These uses are not allowed:

These are contrived examples, but it’s probably not hard to imagine a use case where you need to call api methods conditionally or with parameters that are dependent on other api responses.

Qlik Hooks have another way of executing under these conditions though by exposing a call method that can be called from anywhere. It’s implementation looks like this

There’s a couple new things here. First, when we call useEngineVersion this time, we aren’t passing the second parameter. Without the second parameter, the hook will set up an api call method, but it won’t actually execute when the hook is initialized, only when the call method on engineVersion is run.

Second, we are running engineVersion.call() inside of a useEffect hook. Why? Well if we called it from outside the hook we would end up infinitely re-rendering the App component function. Remember, every time we call engineVersion, the state of engineVersion will update, and every time the state updates, the App component function will rerun, which will again execute engineVersion.call().

useEffect allows us to selectively run code within our App function component, instead of it running every re-render of the component. useEffect takes in a function as its first parameter that will run when necessary. Its second parameter is an array of dependencies that define when the function should run. Whenever a parameter in the dependency array changes its value, the function will re-execute. Since we are passing an empty array, there are no changing dependencies and the code will only execute 1 time when the component is first established.

A real use case for Qlik Hooks call()

Now let’s walk through an example of when we would need to leverage the call method on a qlik hook. In this example, I’m going to create a listbox on our webpage from a field in the Qlik app, and when a user clicks on a listbox item, we want to run SelectListObjectValues on the selected item.

First, we need to connect to our app and create a ListObject

We’re off to a good start. Next we need to get data from the listObject

Ok we’ve got some new stuff going on here. First, we’re running useGetListObjectData on listObject, but we’re also passing in a property invalidations: true. This is telling the hook that whenever the selection state for listObject changes, re-run the GetListObjectData method so we have an updated state of the selected field.

After we get the data, we need to loop through each item in the qMatrix and render an <li> element. We could do this in the return function with something like listObjectData.qResponse[0].qMatrix.map(row => <li...>) but there’s a small issue with this implementation: Whenever the selection state on listObject changes, the GetListObjectData method will run again, temporarily setting the listObjectData’s qResponse to null. This will result in the list disappearing momentarily while new data is being fetched until the new data is received.

Alternatively, we want to set up a way in which we define the state of the listObject items, and only update that state when new data is available. We can do this using React’s useState and useEffect hooks.

When we define const [films, setFilms] = useState([]) we’re creating a new state variable called films that is initialized as an empty array. We also get a setter function setFilms that allows us to update the state of films elsewhere in our code.

Next, the useEffect hook runs a function that checks if listObjectData has a response on it, and then maps that response into an array that is set to the films state. Since the useEffect hook has a dependency list that includes listObjectData the useEffect function will only run when listObjectData changes.

The films array is then used to render <li>’s for each film in the dataset.

Finally, each <li> has an onClick function that calls a function handleClick. Inside this function is where we’ll define how the listObject item will be selected.

One might be inclined to define a function that runs the following code inside handleClick

But remember, this breaks our rule above about calling hooks from inside functions. Instead, we need to set up an object using useSelectListObjectValues outside the function that we can call from inside handleClick

The full solution looks like

I hope this walkthrough demonstrates some clear examples of how Qlik Hooks can help with developing React apps powered by the Qlik Engine. These examples only show a subset of what is possible with Qlik Hooks, but if you want to see more ways it can be leveraged, check out the recipes here.

If there are any issues you encounter while using Qlik Hooks, or even features you would like to see added, create a new issue on the Qlik Hooks GitHub page, or reach out to me on Twitter

--

--

John Bellizzi
The Startup

Web Developer at Axis Group Visual Analytics Practice