NodeGUI is a framework that allows you to write native cross-platform desktop applications. Under the hood, it uses Qt to render the interface. 

It is possible to connect React or Vue

There is also an implementation with Angular from irustm

This article will describe the implementation with the React version. 

Launch and setup

First you need to install cmake
Let’s clone the ready-made template from the developers and run it. 

npm install
npm run dev
npm start

To make the application rebuild every time a change is made to the code, a hot reload is connected to the app component. 

if (module.hot) {
 module.hot.accept(['./app'], function () {
   Renderer.forceUpdate();
 });
}

Unfortunately, if you save the file with any syntax errors, the assembly will crash and you will have to bring the application up again. 

In addition, the specified component must be class-based (only app, any of its child components can be functional). 

It is possible to connect dev tools, modest in their skills: 

npm install --save-dev @nodegui/devtools

or 

npm install -g react-devtools

Launch: 

react-devtools

And slightly change index.js 

Renderer.render(<App />, {
 onInit: (reconciler) => {
   if (process.env.NODE_ENV === 'development') {
     require('@nodegui/devtools').connectReactDevtools(reconciler);
   }
 },
});

The very first element in the interface hierarchy is Window, it is a separate application window, in which everything we need will already be drawn. 

render() {
 return (
   <Window
     windowIcon={winIcon}
     windowTitle="Hello "
     minSize={minSize}
     styleSheet={styleSheet}
   >
     <View style={containerStyle}>
       <Text id="welcome-text">Welcome to NodeGui </Text>
       <Text id="step-1">1. Play around</Text>
       <StepOne />
       <Text id="step-2">2. Debug</Text>
       <StepTwo />
     </View>
   </Window>
 );
}

The View component is a simple container, similar to a div in html. 

Layout

In NodeGUI, there are several ways to build an interface: both by strictly specifying the size of each component, and by adaptive GridView, BoxView, and even using flex. 

BoxView differs from View in that it allows you to set the direction of the position of children. 

<BoxView direction={Direction.LeftToRight}>
 <Button text="Add" on={addHandler} />
 <Button text="Remove" on={removeHandler} />
</BoxView>

The GridView is also a component, to which it is necessary to transfer an n-th number of GridRows to split the container into rows, and in the GridRow, respectively, a GridColumn with the required content. 

Things are much more interesting with flexes implemented with Yoga

Styling and Flex

First, let’s figure out how to style the application. Each component has props like styleSheet and style. 

The first is supplied with a set of styles for the child components of the container, id acts as a selector. 

const styleSheet = `
 #welcome-text {
   font-size: 24px;
   padding-top: 20px;
   qproperty-alignment: 'AlignHCenter';
   font-family: 'sans-serif';
 }

 #step-1, #step-2 {
   font-size: 18px;
   padding-top: 10px;
   padding-horizontal: 20px;
 }
`;

In the second case, we directly pass styles to the component. 

<View style="flex: 1;" />

But it is much more convenient to style using the nodegui-stylesheet library , since it allows you to use objects instead of strings when writing. 

Let’s use the create function to send the styles we need. 

import { create } from 'nodegui-stylesheet';

const style = create({
 wrapper: {
   flex: 1,
 },
 logo: {
   fontSize: 14,
 },
});

Next, we just pass the appropriate style to the style property. 

<View style={style.wrapper}>
 <Text style={style.logo}>Hello</Text>
</View>

The difference between flex layout and others is that it is implemented using styles. 
To enable “flex mode” for a component, you need to assign the flex attribute to it : 1

The larger the number, the more “priority” the component will be and the more space it will take up. 

Styles in nodegui resemble css, but in fact they are not, therefore, not all attributes are available (all available ones can be seen in the Qt documentation). The same, unfortunately, applies to flexes, be careful.

Events

Tracking events for elements is also different from the standard React approach. 

To write an event handler in nodegui-react , you need to use the useEventHandler hook . 

import { View, Button, useEventHandler } from '@nodegui/react-nodegui';
import React from 'react';
import { QPushButtonSignals } from '@nodegui/nodegui';

const TopBar = ({ onAdd }) => {
 const buttonHandler = useEventHandler<QPushButtonSignals>(
   {
     clicked: () => {
       onAdd();
     },
   },
   [onAdd],
 );

 return (
   <View>
     <Button on={buttonHandler} />
   </View>
 );
};

In this case, we are handling the event of the button, so we need to specify the type QPushButtonSignals . The hook itself accepts an object in which a handler is assigned to the events of interest. 

Now, for each button press, the onAdd () function will be called 

Conclusion

We’ve covered everything you need to write interfaces in NodeGUI . Finally, I will say that you should not use nodegui-react for serious projects now, as even the readme of the repository says, because the technology is new and raw, and there are many problems with it.