Use a React Frontend to Create a Webapp

React webapps are not natively supported by DSS, but it’s still possible to integrate a React application into Dataiku DSS with the help of DSS dev plugin and a visual webapp.

In this article, we’ll discuss a few ways you can do this.

Quick start

All of the steps below are implemented in a demo plugin found in this repository.

You can choose to “Fetch from Git repository”, convert it into a dev plugin, and modify it according to your needs instead of creating a new plugin from scratch.

After creating the plugin from git, the demo React app needs to be built. From the $DATADIR/plugins/dev/react/resource/my-app run:

npm install && npm run build

After this step, you can create a new visual webapp inside a project:

../../../_images/11.png ../../../_images/21.png

After modifying the source code of the React app, it needs to be compiled by re-running:

npm run build

Manual dev plugin creation

Create a dev plugin on your Dataiku DSS instance:

../../../_images/31.png

Create the following file structure:

../../../_images/41.png

where:

  • resource/my-app - your react application directory

  • webapps/react/app.js - an empty file required by DSS

  • webapps/react/body.html - a symlink to the resource/my-app/build/index.html

  • webapps/react/webapp.json - a webapp config, for example

{

"meta": {

"label": "Test react app",

"description": "",

"icon": "icon-puzzle-piece"

},


"baseType": "STANDARD", // WARNING: do not change

"hasBackend": "false",

"noJSSecurity": "false",

"standardWebAppLibraries": ["jquery","dataiku"],


"params": [],


"roles": [

/* {"type": "DATASET", "targetParamsKey": "input_dataset"} */

]

}

Finally, add "homepage": "../../resource/my-app/build" to your resource/my-app/package.json

That’s it! Now you just need to reload the webapp from the plugin actions dropdown, and once your React app is built, you can create a new visual webapp in your project.

Using JSX to develop your app

You can use JSX to develop your app. However, you would need to build it first so that DSS could serve compiled javascript files whenever the webapp is opened.

Also, note that you won’t be able to leverage Webpack dev server. Instead, you’ll need to recompile the webapp after changes.

The build should be run manually from the:

$DATADIR/plugins/dev/YOUR_PLUGIN_NAME/resource/YOUR_WEBAPP_NAME

Using a Python-Lib folder

Python-lib is a directory that may contain Python code that is shared between different webapp backends. In this case, it’s empty so you can ignore it to reduce confusion.

In general, if you need a Python backend for your webapp, you need to create a backend.py file defining the endpoints. Here’s an example of how it can be done.

Multiple webapps in one plugin and IDEs for development

You can have multiple webapps in one plugin. Just create another directory next to webapps/react with a similar structure. (Make sure you don’t forget to add a webapp.json and at least modify meta property in it).

For the development process, I’d recommend creating a plugin first and adding a simple React webapp into it. Then you’re not limited to only coding inside DSS, you can either

  • open $DATADIR/plugins/dev/YOUR_PLUGIN_NAME/resource/YOUR_WEBAPP_NAME with your favorite IDE and continue developing the app from it.

  • or use our VSCode integration to edit your plugin code.

In both cases, you are free to develop the webapp completely outside of Dataiku DSS (just by starting the dev server manually from the webapp dir). But to test the API requests served by the python backend, you would need to compile the app and open it from DSS.

Creating a backend for your React webapp

If you’d like to have a backend for your React webapp, here are the steps you’d need to take.

(These instructions below assume you have followed the instructions above and created a plugin. However, you can follow the same steps even if you’ve just created a webapp without a plugin).

  1. Modify $DATADIR/plugins/installed/PLUGIN/webapps/WEBAPP/webapp.json to contain:

"hasBackend": "true"
  1. Add $DATADIR/plugins/installed/PLUGIN/webapps/WEBAPP/backend.py, for example:

import dataiku
from flask import request

@app.route('/first_api_call')
def first_call():
    return json.dumps({"status": "ok", "data": 123})

If you need to contact the DSS API, you can use the dataiku library imported in the beginning.

  1. Modify your react component to send AJAX requests (not the part around first_api_call)

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
function handleClick(e) {
    console.log('The link was clicked.');

    window.$.getJSON(window.getWebAppBackendUrl('first_api_call'), function(data) {
    const output = window.$('<pre />').text('Backend reply: ' + JSON.stringify(data));
    window.$('body').append(output)
    });

}

return (
    <div className="App">
    <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
        Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
        className="App-link"
        href="https://reactjs.org"
        target="_blank"
        rel="noopener noreferrer"
        >
        Learn React
        </a>
        <code onClick={handleClick}>Click me!</code>
    </header>
    </div>
);
}
export default App;

jQuery and getWebAppBackendUrl are added to your page automatically by DSS. In order to overcome the React compilation issues, you would have to refer to them from a window object.

Don’t forget to restart DSS after applying all of the modifications and start the newly created backend when running the webapp.

Appendix

Whenever a user opens a webapp, including the one created in a plugin using React, Dataiku DSS adds some utility code including the window.getWebAppBackendUrl function definition. This happens after the React application is loaded. If your application relies on some data from the backend during initialization, you may face an issue where window.getWebAppBackendUrl is not available yet.

One solution could be to add conditional rendering to the root component of your app:

class App extends React.Component {
constructor(props) {
super(props);
this.state = {
    rendered: false,

dataiku: undefined
};

window.$(document).ready(() => {
    this.setState({ dataiku: window.dataiku });
    this.setState({ rendered: true });
}
);
}

render() {
return (
    <div>
    {this.state.rendered && <h1>DKU API ready: {this.state.dataiku.getWebAppBackendUrl && 'YES'  }</h1>}
    </div>
);
}
}

Next Steps

You can watch this tutorial for more guidance: Configuring a backend for React webapp in Dataiku DSS.