redux-orm: Getting error "Class constructor Record cannot be invoked without 'new'"
Hello,
Just trying out redux orm and I am getting the following error after a basic Model.create
TypeError: Class constructor Record cannot be invoked without 'new'
at new SessionBoundModel (../node_modules/redux-orm/lib/Session.js:77:124) <-- redux-orm internal
at Function.create (../node_modules/redux-orm/lib/Model.js:663:28) <-- session.Record.create
at Object.RECORD_ADDED (state/orm/models.js:39:16) <-- event inside Record.reducer
at Function.reducerForRecord [as reducer] (state/orm/models.js:63:28) <-- Record.reducer
Here is my model:
// My domain is a database; record is a row which has many fields; fields can
// be of many types but they only exist in the context of a record; if a record is deleted
// fields must also be deleted.
export class Record extends Model {}
Record.modelName = 'Record'
Record.fields = {
fields: many('Field')
}
// Please note that makeReducer() isn't doing anything fancy; just matches event.type
// to each specific function and passes session as third argument instead of the model class
// Error is same if reducer is written with a switch statement
Record.reducer = makeReducer(Record, {
[events.RECORD_ADDED] (state, event, session) {
session.Record.create({ id: event.id }) // <--- this is where the error occurs
},
[events.FIELD_ADDED] (state, event, session) {
session.Record.withId(event.record).fields.add(event.id)
},
[events.FIELD_REMOVED] (state, event, session) {
const field = session.Field.withId(event.id)
const record = session.Record.withId(field.record)
record.fields.remove(event.id)
}
})
This also happens with other models (for instance the Field model referenced above). I also tried installing redux-orm v0.8.3 version to see if this was a regression.
Since all the examples show the create static method being called to initialize models, I have not tried attempted to call new directly.
Hope that is clear, let me know if you need more info.
Thanks for the package; I hope it will be useful.
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 1
- Comments: 37 (8 by maintainers)
Commits related to this issue
- add Model.createClass workaround for #53 — committed to Hylozoic/redux-orm by levity 7 years ago
- add test reproducing #53 — committed to haveyaseen/redux-orm by haveyaseen 6 years ago
- add test reproducing #53 — committed to haveyaseen/redux-orm by haveyaseen 6 years ago
- fix #53 by using a Reflect.construct based inheritance mechanism — committed to haveyaseen/redux-orm by haveyaseen 6 years ago
Update: I found a working solution for my own case (i.e. a non-transpiled Electron app).
Basically, redux-orm’s transpiled ES5 code clashes with vanilla ES6 code here — ES6 classes can’t be invoked without
new, but that’s what the library is trying to do. So using aProxyobject is a good workaround. (See the MDN docs.)Here’s a helper function that’ll overwrite
klass.apply()so when it is called, it’ll correctly invoke the class:In your
models.js, wrap your original class objects before registering them:Works for me, YMMV. @tommikaikkonen, this might be something for the docs (if you approve of the workaround and explanation).
To give higher perspective, this issue prevents redux-orm code from being tested in create-react-app environment (which uses jest with this babel configuration).
I would also like to link relevant discussion from babel issues: https://github.com/babel/babel/issues/4269. As far as I can tell from the resolution, it is not possible for transpiled classes to extend from native classes.
With that in mind, I think we should discuss a viable long term solution. Perhaps someone with more knowledge about the codebase than myself can weight in with a conceptual outline of the required changes?
This is the line which causes an error: https://github.com/tommikaikkonen/redux-orm/blob/1b867835f85e542d6d8b64079b7d3f870acdde71/src/Session.js#L31
Huh. So, I actually ran into this myself recently, but didn’t think to search for it exactly. I was able to resolve this by tweaking my Webpack config to have it pull in the
redux--orm/srcfolder so that I used the uncompiled source myself, rather than the precompiled source. In my Webpack config, I added:This somewhat worked for me, but moved the problem somewhere else.
First of all, I didnt seem to run into this problem in my regular code. I only had this occur when writing a test. Once I added the fix above the Model.create() did work but then I go this calling the reducer of the model:
Architecturally, I think the issue is that
Modelis full of static methods that reference a staticthis.sessionfield.I guess there’s a couple aspects that need to be solved:
There’s gotta be something that can be done with, I dunno, unique IDs and lookup tables somehow.
Clearly this is still a pain point.
Is there an alternative way we can implement the overall behavior of Redux-ORM and sessions, without relying on this dynamic subclassing approach?
Alright, v0.10.2 should not require transpilation for ES2017-compatible environments anymore. @Amareis @markerikson @sheppard Would you mind trying the new release? The
resolve.mainFieldsfield can be removed now for anyone usingbabel-preset-env.no working idea yet, let’s leave this issue open to remember “why”.
Sent from iPhone
It would be great if we could solve this on an architectural basis as ES classes are downright backwards-incompatible. However, for now I think the following may suffice (transpiling and testing with ES6 works).
src/Session.js#L29:
Source: https://esdiscuss.org/topic/extending-an-es6-class-using-es5-syntax#content-2
The solution with
Proxydoesn’t work on our side because it cannot be transpiled using Babel.Still reproducible here with babel@6 & redux-orm@0.10.2:
@haveyaseen yeah, it’s working now without
mainFields, big thanks!Heh, one does not simply add preset-stage-2 to babelrc because babelrc from redux-orm take precedence (also, I already have stage-0). But
mainFieldsthing did the trick, thank you mate!That is very unfortunate to hear so I have looked into it some more. If it’s just the spread operator causing the issue, then you can probably fix it by
babel-preset-stage-2usingnpm install babel-preset-stage-2oryarn add babel-preset-stage-2and then'stage-2'tobabel-loader’spresetsarray inwebpack.config.js(or.babelrc).And luckily there is also an alternative to revert to the old behavior! You can apparently ignore the new
pkg.modulekey and use the transpiled files inlib/instead by adding aresolve.mainFieldskey to yourwebpack.config.jslike this:If you choose the latter option, make sure to undo the addition that removes,
redux-ormfrombabel-loader’s excludes.Hope this helps you so you don’t have to miss out on our new performance improvements!
I tried adding
"module": "src/index.js"to package.json (see #192). This fixed the issue for me with the latest create-react-app and babel. Does the fix work for anyone else?@carlo Thanks for sharing your solution! Update: It unfortunately does not work properly. I’m using redux-orm in a server-only (node 8) environment.
@nealoke yes, I noticed you had a different issue which caused the same error message.