Duplicate constructor in same class in JSX webpack build - reactjs

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.

Related

How to solve problem with "Global CSS cannot be imported" in nextjs app?

I try to use your library in NextJS app but I accuse following error:
./node_modules/normalize.css/normalize.css
Global CSS cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-npm
Location: node_modules/react-fullpage-accordion/dist/full-page-accordion.js
I imported all like your example is written
import { FullpageAccordion, Panel } from 'react-fullpage-accordion';
import "react-fullpage-accordion/dist/react-fullpage-accordion.css";
Update.
I renamed react-fullpage-accordion.css to react-fullpage-accordion.module.css, and then try to importem as well.
Error still occur.
./node_modules/normalize.css/normalize.css
Global CSS cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-npm
Location: node_modules/react-fullpage-accordion/dist/full-page-accordion.js
think error is made by this following code
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
require("normalize.css");
var _panelContext = require("./panel-context");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
/* eslint-disable react/forbid-prop-types, no-unused-vars, import/no-unresolved, import/extensions */
var FullpageAccordion = function FullpageAccordion(_ref) {
var children = _ref.children,
height = _ref.height;
return /*#__PURE__*/_react["default"].createElement(_panelContext.PanelContextProvider, null, /*#__PURE__*/_react["default"].createElement("div", {
className: "panels",
"data-testid": "panels",
style: {
height: height || '100vh'
}
}, children));
};
FullpageAccordion.defaultProps = {
height: undefined
};
FullpageAccordion.propTypes = {
children: _propTypes["default"].node.isRequired,
height: _propTypes["default"].string
};
var _default = FullpageAccordion;
exports["default"] = _default;
but I am afraid of changing something in third part code.

Dynamic import in different folder

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

Can I create a TypeScript class within a function and refer to its parameters?

E.g. in angularJS I may use the following construction:
myApp.factory('MyFactory', function(injectable) {
return function(param) {
this.saySomething = function() {
alert("Param=" + param + " injectable=" +injectable);
}
};
});
This can later be used like this:
function(MyFactory) {
new MyFactory().saySomething();
}
When the function passed to the method factory gets invoked, the param injectable is caged and will further be available to new instances of MyFactory without any need to specify that parameter again.
Now I want to use TypeScript and obviously I want to specify that my MyFactory is newable, and has a function saySomething. How could I do this elegantly?
I could write something like this:
class MyFactory {
constructor(private injectable, private param) {}
saySomething() {
alert(...);
}
}
myApp.factory('myFactory', function(injectable) {
return function(param) {
return new MyFactory(injectable, param);
}
});
But this changes the API:
function(myFactory) {
myFactory().saySomething();
}
I wonder if it could be more elegant, because I like how the "new" expresses quite clearly that a new unique object is created and this object creation is the whole purpose of the factory.
** Edit: TypeScript >= 1.6 supports class expressions and you can now write things like:
myApp.factory(injectable: SomeService) {
class TodoItem {
...
}
}
** Original answer:
I have the same problem: with AngularJS and ES5, I enjoy dependency injection not polluting constructors and be able to use the new keyword.
With ES6 you can wrap a class inside a function, this is not yet supported by TypeScript (see https://github.com/Microsoft/TypeScript/issues/307).
Here what I do (MyFactory is now class TodoItem from a todo app to be more relevant):
class TodoItem {
title: string;
completed: boolean;
date: Date;
constructor(private injectable: SomeService) { }
doSomething() {
alert(this.injectable);
}
}
class TodoItemFactory() {
constructor(private injectable: SomeService) { }
create(): TodoItem {
return new TodoItem(this.injectable);
}
// JSON from the server
createFromJson(data: any): TodoItem {
var todoItem = new TodoItem(this.injectable);
todoItem.title = data.title;
todoItem.completed = data.completed;
todoItem.date = data.date;
return todoItem;
}
}
// In ES5: myApp.factory('TodoItem', function(injectable) { ... });
myApp.service('TodoItemFactory', TodoItemFactory);
class TodosCtrl {
// In ES5: myApp.controller('TodosCtrl', function(TodoItem) { ... });
constructor(private todoItemFactory: TodoItemFactory) { }
doSomething() {
// In ES5: var todoItem1 = new TodoItem();
var todoItem1 = this.todoItemFactory.create();
// In ES5: var todoItem2 = TodoItem.createFromJson(...)
var todoItem2 = this.todoItemFactory.createFromJson(
{title: "Meet with Alex", completed: false}
);
}
}
This is less elegant than with ES5 and functions (and not using classes with TypeScript is a no go) :-/
What I would like to write instead:
#Factory
#InjectServices(injectable: SomeService, ...)
class TodoItem {
title: string;
completed: boolean;
date: Date;
// No DI pollution
constructor() { }
saySomething() {
alert(this.injectable);
}
static createFromJson(data: string): TodoItem {
...
}
}
#Controller
#InjectFactories(TodoItem: TodoItem, ...)
class TodosCtrl {
constructor() { }
doSomething() {
var todoItem1 = new TodoItem();
var todoItem2 = TodoItem.createFromJson({title: "Meet with Alex"});
}
}
Or with functions:
myApp.factory(injectable: SomeService) {
class TodoItem {
title: string;
completed: boolean;
date: Date;
// No constructor pollution
constructor() { }
saySomething() {
alert(injectable);
}
static createFromJson(data: string): TodoItem {
...
}
}
}
myApp.controller(TodoItem: TodoItem) {
class TodosCtrl {
constructor() { }
doSomething() {
var todoItem1 = new TodoItem();
var todoItem2 = TodoItem.createFromJson({title: "Meet with Alex"});
}
}
}
I could write something like this
This is what I do
Can I create a TypeScript class within a function
No it needs to be at the top level of the file or in a module. Just FYI if were able to create it inside a function the information would be locked inside that function and at least the type info would be useless.
What's the reason for instantiating multiple instances of MyFactory? Would you not want a single instance of your factory to be injected into your dependent code?
I think using the class declaration you provided will actually look like this once injected:
function(myFactory) {
myFactory.saySomething();
}
If you are really needing to pass a constructor function into your dependent code, then I think you will have to ditch TypeScript classes, since they can't be defined inside of a function which means you would have no way to create a closure on a variable injected into such function.
You do always have the option of just using a function in TypeScript instead of a class. Still get the strong typing benefits and can call 'new' on it since it is still a .js function at the end of the day. Here's a slightly more TypeScriptiffied version:
myApp.factory('MyFactory', (injectable: ng.SomeService) => {
return (param: string) => {
return {
saySomething: () {
alert("Param=" + param + " injectable=" +injectable);
}
};
};
});

Coffeescript and Backbone.js + linting issue with grunt.js

I'm having a bit of an issue with a class extending the Backbone.Model.
Using the following class …
class Turtles extends Backbone.Model
idAttribute: "_id"
legs: [0,1,3,5]
urlRoot: '/turtles'
module.exports = Turtles
grunt.js is throwing this error when linting.
[L21:C18] 'Turtles' is already defined.
function Turtles() {
The output of the compile js file looks like this:
(function() {
var Turtles,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Turtles = (function(_super) {
__extends(Turtles, _super);
function Turtles() {
return Turtles.__super__.constructor.apply(this, arguments);
}
Turtles.prototype.idAttribute = "_id";
Turtles.prototype.points = [0, 1, 3, 5];
Turtles.prototype.categories = ['story', 'tech', 'design', 'bug'];
Turtles.prototype.urlRoot = '/cards';
return Turtles;
})(Backbone.Model);
module.exports = Turtles;
}).call(this);
This output is very similar to some views I have extended using class Application extends Backbone.View, so I'm not sure why this model would be failing linting when all my views and collections arent.
That all being said, replacing class Turtles extends Backbone.Model with Turtles = Backbone.Model.extend works find and causes no errors.
Just wondered if anyone has had experience with this before, or perhaps can spot an issue.
Thanks

ExtJs - constructor overriding my instances

I use ExtJs 4.1 and DeftJs.
Some class is defined with a constructor like that:
Ext.define( 'A.helper.Report', {
config: {
conf : null,
viewMain : null
},
constructor: function( oConfig ) {
this.conf = oConfig.conf;
this.viewMain = oConfig.viewMain;
this.initConfig( oConfig );
}
...
Now, I create several instances of this class like that:
var class1 = Ext.create( 'A.helper.Report', {
conf: someValue,
viewMain: someObject
} );
var class2 = Ext.create( 'A.helper.Report', {
conf: otherValue,
viewMain: otherObject
} );
When using these instances, although giving them different oConfig data, both class1 and class2 now have the data of the 2nd oConfig.
So when calling this.conf in both instances, I get someValue.
How can I keep the data of already created instances?
Solution:
I wrote
Ext.define( 'A.helper.Report', {
...
references: {}
...
and put my instances in there, overriding old instances.
Switched to references: null helped.
...
Be careful to not messing around with prototype objects...
Rewritten answer
You are doing it the wrong way.
See this working JSFiddle
Ext.define('A.helper.Report', {
config: {
conf : null,
viewMain : null
},
constructor: function(cfg) {
this.initConfig(cfg);
}
});
var class1 = Ext.create('A.helper.Report',{
conf: 66,
viewMain: 'Bear'
});
var class2 = Ext.create('A.helper.Report',{
conf: 88,
viewMain: 'Eagle'
});
class1.getConf(); // 66
class1.getViewMain(); // Bear
class2.getConf(); // 88
class2.getViewMain(); // Eagle

Resources