How to do it...

We want to add some functionality to our app of the kind that a typical desktop would have. Let's see how can we do that. The key to adding Node functions to your app is to use the remote module in Electron. With it, your browser code can invoke methods of the main process, and thus gain access to extra functionality. 

See https://github.com/electron/electron/blob/master/docs/api/remote.md for more on the remote module. There is also extra information that might come in handy at https://electronjs.org/docs/api/remote.

Let's say we wanted to add the possibility of saving the list of a country's regions to a file. We'd require access to the fs module to be able to write a file, and we'd also need to open a dialog box to select what file to write to. In our serviceApi.js file, we would add the following functions:

// Source file: src/regionsApp/serviceApi.js

/* @flow */

const electron = window.require("electron").remote;

.
.
.

const fs = electron.require("fs");

export const writeFile = fs.writeFile.bind(fs);

export const showSaveDialog = electron.dialog.showSaveDialog;

Having added this, we can now write files and show dialog boxes from our main code. To use this functionality, we could add a new action to our world.actions.js file:

// Source file: src/regionsApp/world.actions.js

/* @flow */

import {
getCountriesAPI,
getRegionsAPI,
showSaveDialog,
writeFile
} from "./serviceApi";

.
.
.

export const saveRegionsToDisk = () => async (
dispatch: ({}) => any,
getState: () => { regions: [] }
) => {
showSaveDialog((filename: string = "") => {
if (filename) {
writeFile(filename, JSON.stringify(getState().regions), e =>
e && window.console.log(`ERROR SAVING ${filename}`, e);
);
}
});
};

When the saveRegionsToDisk() action is dispatched, it will show a dialog to prompt the user to select what file is to be written, and will then write the current set of regions, taken from getState().regionsto the selected file in JSON format. We just have to add the appropriate button to our <RegionsTable> component to be able to dispatch the necessary action:

// Source file: src/regionsApp/regionsTableWithSave.component.js

/* @flow */

import React from "react";
import PropTypes from "prop-types";

import "../general.css";

export class RegionsTable extends React.PureComponent<{
loading: boolean,
list: Array<{
countryCode: string,
regionCode: string,
regionName: string
}>,
saveRegions: () => void
}> {
static propTypes = {
loading: PropTypes.bool.isRequired,
list: PropTypes.arrayOf(PropTypes.object).isRequired,
saveRegions: PropTypes.func.isRequired
};

static defaultProps = {
list: []
};

render() {
if (this.props.list.length === 0) {
return <div className="bordered">No regions.</div>;
} else {
const ordered = [...this.props.list].sort(
(a, b) => (a.regionName < b.regionName ? -1 : 1)
);

return (
<div className="bordered">
{ordered.map(x => (
<div key={x.countryCode + "-" + x.regionCode}>
{x.regionName}
</div>
))}
<div>
<button onClick={() => this.props.saveRegions()}>
Save regions to disk
</button>
</div>
</div>
);
}
}
}

We are almost done! When we connect this component to the store, we'll simply add the new action, as follows:

// Source file: src/regionsApp/regionsTableWithSave.connected.js

/* @flow */

import { connect } from "react-redux";

import { RegionsTable } from "./regionsTableWithSave.component";

import { saveRegionsToDisk } from "./world.actions";

const getProps = state => ({
list: state.regions,
loading: state.loadingRegions
});

const getDispatch = (dispatch: any) => ({
saveRegions: () => dispatch(saveRegionsToDisk())
});

export const ConnectedRegionsTable = connect(
getProps,
getDispatch
)(RegionsTable);

Now, everything's ready—let's see it working.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.156.250