Dynamic import in different folder - reactjs

I have some trouble to import dynamicaly a class.
I use alias for this projet :
config.resolve.alias = {
App: path.resolve('./src/'),
Reactive: path.resolve('./app/')
}
I want to import a list of class :
const classes = {
foo: 'App/Foo',
bar: 'App/Bar'
};
let list = {};
for(var c in classes) {
(async (k, v, list) => {
const m = await import(`${v}`);
list[k] = new m.default();
})(c, classes[c], list);
}
This script is called in app, and all imported classes in src.
The error is simple : Cannot find module 'App/Foo'.
When I check the last entry of error's log :
var map = {
"./OtherClass1": [
"./app/OtherClass1.js"
],
"./OtherClass1.js": [
"./app/OtherClass1.js"
],
"./OtherClass2": [
"./app/OtherClass2.js"
],
"./OtherClass2.js": [
"./app/OtherClass2.js"
]
};
function webpackAsyncContext(req) {
var ids = map[req];
if(!ids)
return Promise.reject(new Error("Cannot find module '" + req + "'."));
return Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {
return __webpack_require__(ids[0]);
});
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.id = "./app lazy recursive ^.*$";
module.exports = webpackAsyncContext;
So, the error is legit, because the map does not contain Foo and Bar classes in src, only those in app.
How can I specify to Webpack to check in both folders, recursively?
But, when I test this, it's work fine :
for(var c in classes) {
(async (k, v, list) => {
const m = await import(`${"App/Foo"}`);
list[k] = new m.default();
})(c, classes[c], list);
}

use react import to import your file and use file.classname to call them
eg import claases from '/src';
and use it link
app = classes.myfile

Related

How to use custom style loader in Vite

We have a react project and using webpack for bundling but also we want to try vite too. Webpack bundle css files from style-loader.js too. In style-loader.js we have some rules which are related to components and components are added to node modules. My rule's aim is mainly importing css files from node_modules components. When we run our project with vite, Our custom scss files does not override css which came from components. Is there any solution for override or Is there any way to use a custom style loader in vite ?
Our custom style loader webpack-dev is;
module: {
rules: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: './config/webpack/style-loader'
},
]}
Our style-loader.js file is;
const babylon = require('babylon');
const traverse = require('babel-traverse').default;
const fs = require('fs');
module.exports = function (source) {
var astResult = babylon.parse(source, {
sourceType: "module",
ranges: true,
plugins: [
"jsx",
"objectRestSpread",
"flow",
"typescript",
"decorators",
"doExpressions",
"classProperties",
"classPrivateProperties",
"classPrivateMethods",
"exportExtensions",
"asyncGenerators",
"functionBind",
"functionSent",
"dynamicImport",
"numericSeparator",
"optionalChaining",
"importMeta",
"bigInt",
"optionalCatchBinding"
]
});
let addedIndexCounter = 0;
let isViewDirty = false;
traverse(astResult, {
enter: function (path) {
let node = path.node;
if (node.type == 'ImportDeclaration' &&
node.source &&
node.source.type == 'StringLiteral' &&
node.source.value &&
node.source.value.indexOf('#packagename') >= 0 &&
node.source.value.indexOf('core') < 0 &&
node.source.value.indexOf('.css') < 0) {
if(fs.existsSync('./node_modules/' + node.source.value + '/styles.css')) {
let starting = node.end;
starting += addedIndexCounter;
let targettacCss = "; import '" + node.source.value + "/styles.css';"
addedIndexCounter += targettacCss.length;
source = source.substring(0, starting) + targettacCss + source.substring(starting);
isViewDirty = true;
}
}
}
});
/*if(isViewDirty){
let fileName = "view_" + (new Date()).toISOString().slice(0, 10)+"_" + Math.random().toString(35).substr(2,10);
fs.writeFileSync('./logs/views/' + fileName, source);
}*/
return source;
};
You can use plugins to achieve your feature, the following is my general idea.
// vite.config.js
import { defineConfig } from "vite";
import customerPlugin from "./plugin/customer-plugin";
export default defineConfig(() => {
return {
// ..
plugins: [customerPlugin()] // Put your plugin here
};
});
// ./plugin/customer-plugin.js
const customerPlugin = () => {
return {
name: "customer-transform",
transform(code, id) {
// id = "/some/path/xxx.js"
if (!id.endsWith(".js")) return; // Only transform js file.
let resultCode = "";
// Paste your transform logic here.
return resultCode;
}
};
};
export default customerPlugin;
reference: https://vitejs.dev/guide/api-plugin.html

vscode findFiles returns nothing but npm glob returns correct results

I'm writing and vscode extension in which I need a list of the test files inside workspace.
To find the test files I'm using the default testMatch from the jest.config.js which is:
[
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)'
]
My problem is that vscode.workspace.findFiles returns empty array and I cannot set it up to get correct results, but using Glob package the output is correct.
protected async findTestFiles(
matchTestsGlobPatterns: string[]
): Promise<vscode.Uri[]> {
const testFilesUris: vscode.Uri[] = [];
const glob_testFilesUris: vscode.Uri[] = [];
const { name: workspaceName, workspaceFolders } = vscode.workspace;
if (workspaceName === undefined || workspaceFolders === undefined) {
throw new Error(`No active workspace${!workspaceFolders ? ' folders' : ''}.`);
}
for (let folderIdx = 0; folderIdx < workspaceFolders.length; folderIdx++) {
const folder = workspaceFolders[folderIdx];
// - by vscode.workspace.findFiles
for (let patternIdx = 0; patternIdx < matchTestsGlobPatterns.length; patternIdx++) {
const currentPattern = matchTestsGlobPatterns[patternIdx];
const pattern = new vscode.RelativePattern(
folder.uri.fsPath,
currentPattern
);
const files = await vscode.workspace.findFiles(
pattern,
'**/node_modules/**'
);
testFilesUris.push(...files);
}
console.log('by [vscode.workspace.findFiles]', testFilesUris.length);
// - by npm Glob
var glob = require('glob');
for (let patternIdx = 0; patternIdx < matchTestsGlobPatterns.length; patternIdx++) {
const currentPattern = matchTestsGlobPatterns[patternIdx];
const files: any[] = await new Promise((resolve, reject) => {
glob(
currentPattern,
{
absolute: true,
cwd: folder.uri.fsPath,
ignore: ['**/node_modules/**']
},
function (err: Error, files: any[]) {
if (err) {
return reject(err);
}
resolve(files);
}
);
});
glob_testFilesUris.push(...files);
}
console.log('by [npm Glob]', glob_testFilesUris.length);
}
// #todo: remove duplicates.
return testFilesUris;
}
The example console output of this function for some project is:
by [vscode.workspace.findFiles] 0
by [npm Glob] 45
Project structure:
rootFolder
src
__tests__
files.test.ts
...
utils
array.test.ts
...
So my question is how do I call vscode.workspace.findFiles to get correct results, or is there known problem with this function?
I have found some kind of answer to the question.
The problem is ?(x) in patterns. The vscode.workspace.findFiles does not work with this pattern as other packages do. If remove it from mentioned glob patterns they work except the .jsx | .tsx files are ommited.
After deep dive into vscode github's issues I have learned (here) that vscode.workspace.findFiles does not support extended patterns like ?(patterLike)

Pass an Array as a query String Parameter node.js

How can I pass an array as a query string parameter?
I've tried numerous ways including adding it to the path but i'm not able to pull the array on the back end.
If I hard code the array it works fine, but when I try to pass the array from my front end to the backend it does not work properly.
Can anyone point me in the right direction?
FrontEnd
function loadJob() {
return API.get("realtorPilot", "/myTable/ListJobs", {
'queryStringParameters': {
radius,
availableServices,
}
});
BackEnd
import * as dynamoDbLib from "./libs/dynamodb-lib";
import { success, failure } from "./libs/response-lib";
export async function main(event, context) {
const data = {
radius: event.queryStringParameters.radius,
availableServices: event.queryStringParameters.availableServices,
};
// These hold ExpressionAttributeValues
const zipcodes = {};
const services = {};
data.radius.forEach((zipcode, i) => {
zipcodes[`:zipcode${i}`] = zipcode;
});
data.availableServices.forEach((service, i) => {
services[`:services${i}`] = service;
});
// These hold FilterExpression attribute aliases
const zipcodex = Object.keys(zipcodes).toString();
const servicex = Object.keys(services).toString();
const params = {
TableName: "myTable",
IndexName: "zipCode-packageSelected-index",
FilterExpression: `zipCode IN (${zipcodex}) AND packageSelected IN (${servicex})`,
ExpressionAttributeValues : {...zipcodes, ...services},
};
try {
const result = await dynamoDbLib.call("scan", params);
// Return the matching list of items in response body
return success(result.Items);
} catch (e) {
return failure(e.message);
}
}
Pass a comma seperated string and split it in backend.
Example: https://example.com/apis/sample?radius=a,b,c,d&availableServices=x,y,z
And in the api defenition split the fields on comma.
const data = {
radius: event.queryStringParameters.radius.split(','),
availableServices: event.queryStringParameters.availableServices.split(',')
};

Is it possible to retrieve a component's instance from a React Fiber?

Before v16 of React -- that is, before the introduction of React fibers -- it was possible to take a DOM element and retrieve the React component instance as follows:
const getReactComponent = dom => {
let found = false;
const keys = Object.keys(dom);
keys.forEach(key => {
if (key.startsWith('__reactInternalInstance$')) {
const compInternals = dom[key]._currentElement;
const compWrapper = compInternals._owner;
const comp = compWrapper._instance;
found = comp;
}
});
return found || null;
};
This no longer works for React v16, which uses the new Fiber implementation. Specifically, the above code throws an error at the line const comparWrapper = compInternals._owner because there is no _owner property anymore. Thus you cannot also access the _instance.
My question here is how would we retrieve the instance from a DOM element in v16's Fiber implementation?
You may try the function below (updated to work for React <16 and 16+):
window.FindReact = function(dom) {
let key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$"));
let internalInstance = dom[key];
if (internalInstance == null) return null;
if (internalInstance.return) { // react 16+
return internalInstance._debugOwner
? internalInstance._debugOwner.stateNode
: internalInstance.return.stateNode;
} else { // react <16
return internalInstance._currentElement._owner._instance;
}
}
Usage:
var someElement = document.getElementById("someElement");
FindReact(someElement).setState({test1: test2});
React 17 is slightly different:
function findReact(dom) {
let key = Object.keys(dom).find(key => key.startsWith("__reactFiber$"));
let internalInstance = dom[key];
if (internalInstance == null) return "internalInstance is null: " + key;
if (internalInstance.return) { // react 16+
return internalInstance._debugOwner
? internalInstance._debugOwner.stateNode
: internalInstance.return.stateNode;
} else { // react <16
return internalInstance._currentElement._owner._instance;
}
}
the domElement in this is the tr with the data-param-name of the field you are trying to change:
var domElement = ?.querySelectorAll('tr[data-param-name="<my field name>"]')

Duplicate constructor in same class in JSX webpack build

I'm having an issue with some code I wrote that's utterly stumped me.
The main JSX tutorial available at the JSX Github Page has an example class called Point, which looks like:
class Point {
var x = 0;
var y = 0;
function constructor() {
}
function constructor(x : number, y : number) {
this.set(x, y);
}
function constructor(other : Point) {
this.set(other);
}
function set(x : number, y : number) : void {
this.x = x;
this.y = y;
}
function set(other : Point) : void {
this.set(other.x, other.y);
}
}
That class has a clear example of a multiple constructor types which I'm familiar from my C++ days. It even has a defined copy constructor, which I think is great.
However, if I got and create a similar class for use by me:
export default class MutableDataStore {
constructor() {
this.data = [];
this.settings = {};
}
//Copy constructor
constructor(other : MutableDataStore) {
this.data = other.data.slice();
this.settings = Object.assign({}, this.settings);
}
//...Other functions omitted
}
I get the following error in my webpack build:
ERROR in ./src/stores/helper-classes/mutabledatastore.jsx
Module build failed: SyntaxError: Duplicate constructor in the same class (8:1)
I'm completely stumped by this, since I can't find anything similar on the web about this, unless it seems to be a transient issue.
My webpack.config.js is:
var webpack = require("webpack");
var path = require("path");
var src = path.resolve(__dirname, "src");
var app = path.resolve(__dirname, "app");
var config = {
entry: src + "/index.jsx",
output: {
path: app,
filename: "javascript.js"
},
module: {
loaders: [{
include: src,
loader: "babel-loader"
}]
}
};
module.exports = config;
and my babel presets are es2015 and react.
Any help would be appreciated!
As loganfsmyth said in the comments, there can only be one constructor in an ES6 class. You can get the desired effect by either checking if other is set in the construct or by providing a default value for the parameter
export default class MutableDataStore {
constructor(other : MutableDataStore) {
this.data = other ? other.data.slice() : [];
this.settings = other ? Object.assign({}, other.settings) : {};
}
//...Other functions omitted
}
// or
export default class MutableDataStore {
constructor(other : MutableDataStore = { data: [], settings: {} }) {
this.data = other.data.slice();
this.settings = Object.assign({}, other.settings);
}
//...Other functions omitted
}
As a side not, I think you might have intended the copy constructor to copy the settings from other, not this.

Resources