I have a React app that runs in Electron. Throughout all of the renderer process code, I've been using axios as follows:
import React from 'react';
import axios from 'axios';
import { useQuery } from 'react-query';
...
const { data: queryResponse, isLoading } = useQuery(
[query, getParameters], () => {
const url = new URL(`https://www.devel.server/${query}`);
url.search = new URLSearchParams(getParameters);
return axios.get(url);
}
);
Now I tried to run the same code in the main process, and suddenly I'm getting exceptions:
const { app, BrowserWindow, Menu, ipcMain } = require('electron');
const { odtParse } = require('./main/odt-parser.js');
const shell = require('electron').shell;
const path = require('path');
import axios from 'axios';
ipcMain.on('generate-employee-contract', (event, employeeId) => {
const url = new URL('https://www.devel.server/employee-contract-summary');
url.search = new URLSearchParams({ employeeId });
axios.get(url).then(function (response) {
const filename = odtParse('./assets/Contract.odt', response.variables, response.conditions);
shell.openPath(path.join(__dirname, filename));
})
});
This is the error I'm getting from the axios.get() call:
UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received an instance of URL
What's going on? Why does same code work in one process but not in the other? Is it using different axios instances somehow?
EDIT: as requested, the output of console.log(url):
URL {
href: 'https://www.devel.server/employee-contract-summary?employeeId=377',
origin: 'https://www.devel.server',
protocol: 'https:',
username: '',
password: '',
host: 'www.devel.server',
hostname: 'www.devel.server',
port: '',
pathname: '/employee-contract-summary',
search: '?employeeId=377',
searchParams: URLSearchParams { 'employeeId' => '377' },
hash: ''
}
There's a difference between URL implementation in Chromium (used by renderer processes) and Node (used by the main process) environments. In particular, WHATWG-compliant URL class is global (and always available) in the supporting browsers, yet became available globally only since Node 10.x; before that, it had to be only accessed through require('url').URL import.
It seems that this difference doesn't play well with axios type checks on its url parameter, causing ERR_INVALID_ARG_TYPE error. One way around it is avoiding passing URL completely, transforming it into string instead:
const url = new URL('https://www.devel.server/employee-contract-summary');
url.search = new URLSearchParams({ employeeId });
const urlString = url.toString(); // supported by URL class
axios.get(urlString).then(/* ... */)
Another approach worth checking is ensuring the code in the main process supplies axios with correct adapter, which might also eliminate the issue (as adapter should be responsible for bridging gaps like this).