I'm trying to build a game in Clojurescript using Reagent and React-Pixi, but as soon as I try to do anything I get:
Error: Invariant Violation: PIXIStage.render() A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
A minimal case to reproduce this is:
(ns react-sprites.core
(:require [cljsjs.react-pixi]
[reagent.core :as r]))
(def stage (r/adapt-react-class js/ReactPIXI.Stage))
(defn root [] [stage {:width 300 :height 300}])
(r/render-component [root]
(. js/document (getElementById "app")))
specifically, using the react-pixi and reagent versions:
[reagent "0.6.0-rc"]
[cljsjs/react-pixi "0.8.1-0"]
Additional Information
I've gone and traced around in the debugger, and the invariant violation is being thrown on a canvas that's being generated by React.createElement("canvas") in ReactPIXI's render() method, so apparently the canvas being created isn't a valid ReactComponent. I really don't know where to go from here.
It turns out that the problem here came down to a version incompatibility. I thought I was running on Reagent 0.6 and using the latest React, but it seems like the app didn't get properly updated and was still using 0.5.1 which uses a React version that's incompatible with react-pixi's. To fix it, I had to force the update, at which point it started working. While reproducing this issue I also had problems with the browser cache.
In summary, things worth trying include:
$ lein clean
# edit the dependency information
$ lein figwheel
Clearing cache
Downgrading then upgrading versions (perhaps?)
As a side note, I was led astray by a combination of other error messages I found while debugging, some of which warn about the possibility that there were multiple React versions running on the page. Since I didn't get one of those, I had prematurely ruled out the possibility.
There is a library called puck, which is a ClojureScript wrapper around PixiJS. This may be another route to apply ClojureScript in building game.
Related
I've just updated some depencencies in a React project using npm install and the updated project works nicely on all browser except Safari.
On Safari it shows a blanks screen and an error in the console:
SyntaxError: Invalid regular expression: invalid group specifier name
file: 2.f80ba52b.chunk.js
I can exclude breaking changes from updated dependencies, otherwise it would have broken on other browsers too. Despite that, I cannot figure out what is causing it.
Even if similar questions exist, and the root cause has been already recognized as the missing Safari support for lookbehind regex, I would like to provide a general way to handle those situations where, as described in the main question, you can not just fix a line of code - for example when the issue is caused by an external library.
How to handle broken external depencencies
In my case, the bug had been introduced with draft-js-utils 1.4.1, so I solved it downgrading to the first know working version (1.4.0). In order to achieve this, I edited the package.json file changing the dependency line from
"draft-js-utils": "^1.4.0"
to
"draft-js-utils": "1.4.0"
TIP: Avoiding the caret range, you can stick it to a specific version.
How to find broken external depencencies
The only way to find out what dependencies have been affected by this bug is to look for the error message in Github/Gitlab search - currently almost 300 public repositories have a related issue opened.
The hardest thing about this bug is that it could be hidden inside transitive dependencies.
You might not even know you are using that package.
If you are not lucky enough to spot it using a Github/Gitlab search, you could try with a local search using your IDE or grep. You need to look for the lookbehind symbols ?<!:
grep -r "?<\!" node_modules
Being a last resort, this approach could be either very slow or produce a huge-and-hard-to-read output.
A sad note
It looks like Webkit developers are not going to add lookbehind regex support soon - the issue has been created in July 2017 without receiving attention from them. Moreover, even if the Safari's issue has been recognized and tracked, no polyfill exists to fix it at the build level (e.g. using Babel).
I just want to add that I spent a week downgrading Babel and other packages to pre-2018 packages, only to realise that my problem was in a helper function within my own code that was to filter for malicious html code.
#lifeisfoo mentions to grep for the string '?<!' above in node_modules, but i recommend also grepping the entire project.
fyi, my regex that was breaking Safari was '?<=!'. Which is also an unsupported lookbehind
I tested my regex: (?<=![)(.*?)(?=]) in Safaris regex tester https://www.regextester.com/ and the output says 'Lookbehind is not supported in Javascript'
To end, I found Safaris console error message worthless and spread around the 10,000s of lines of the bundle.js, giving the impression that the issue was within the packages/dependancies, which it clearly was not.
I spent ages downgrading the packages only to find the same error message appear on a different line of the bundle.js code.
This problem is killing me, but I keep getting this error when I compile and run (I am using .NET Core 3.0 with react app):
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
The error points to my ../src/index.js file:
Here is the error displayed
Here is the code that is flagged with the invalid hook call error
I'm not sure what's going on, i spent the past 3 hours trying to fix it but I just can't get the homepage to show.
I understand the hooks error, but I don't understand why its getting called.
I have the matching versions of React and React DOM, 16.13.1
For my react components, I use classes.
I'm not sure how to check for different copies of react
I'm quite new to React so maybe i misunderstood or messed up somewhere, please help me here, thank you.
EDIT:
Check if redux is installed on the client. This error occurs when it isn't installed on client directory but server directory.
check package.json of client.
Maybe a crazy solution but in my case nothing was actually wrong with my code. I was going nuts trying to find the error. But what actually helped, was upgrading the version of Typescript installed in my project from 4.4 to 4.9. Don't see any evident connection but after the upgrade everything worked like a charm. :)
I have a sort of a "monorepo", one big project consisting of a few smaller projects that use React.
I'm trying to break these up into three separate repositories, lets call them Core, Application1, and Application2
The Core is a dependency of both applications, and the Core depends on React, because it defines some React component classes. The applications both also use React.
When I tried to build this all together (using Parcel bundler), I am getting a final bundle which at runtime gives the Invalid Hook Call warning in one (but not both) of the applications.
On that page (or in the error message), it says that the error could be caused by one o these:
You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app.
I have checked that #1 is not true, and I'm not even using hooks in any way that I am aware of, so the problem is seems to be multiple versions of React.
I gathered from reading about this that it was a mistake for my Core library to declare React as a dependency, and that it should instead declare it in peerDependencies. That made the Application stop giving the error, but it also made my Core library start having a bunch of Typescript errors and failing to be able to run the unit tests (which rely on React, using Jest/Enzyme to render and validate DOM).
Since specifying React in peerDependencies caused it not to be installed in the node_modules of Core, I decided that I should probably include React in both the peerDependencies and the devDependencies of Core. That fixes the Core library again but breaks the Application.
I'm not really sure of the following:
Why one of my applications fail due to duplicate React copies and the other doesn't, since they seem pretty symmetrical to each other.
Why, even though I only specify React in peerDependencies and devDepenencies in Core I still would get a duplicate copy of React in the dependent application
Whether the method used to bring Core in to the application has any bearing on this. (one method I'm trying is package.json I specify core as a "file:../" style of URL. Another alternative is to use "yarn link", or possibly to do both of these, and I'm not sure whether this has any effect on what ends up in node_modules underneath the application folder or on what gets bundled)
What is the right way to include React in both an Application and a library, in such a way that both of those projects have React available but there does not end up being duplicates in the Application causing this hook error (or, just taking up extra space).
Answering my own question.
I found the following issue helpful: https://github.com/facebook/react/issues/14257
Various different suggestions were made in the comments of ways to solve this problem, either by npm link or yarn linking the react library from the library to the application, or vice versa. Those all seemed promising, since the idea is to make sure that all of the different references to React are actually pointing to the same place. Unfortunately none of those worked for me. (e.g. the answers by JerryGreen and Kas in that issue)
Another user, dcecile, suggested using webpack's alias feature, but I'm not using webpack.
resolve: {
alias: { react: require.resolve("react") }
},
Parcel has a similar alias feature but can't be used in quite the same way because it's used in the package.json file so things like require.resolve can't be called like they are in webpack's js config file.
I ended up finding a way to use Parcel's alias feature to do what I wanted, based on another example from https://github.com/jaredpalmer/tsdx/issues/64 from user jaredpalmer. In my situation, I'm adding this to the application's package.json, and it appears to get rid of the duplication problem and the "Invalid Hook Call" error:
"alias": {
"react": "../my-core-library/node_modules/react",
},
I would like to get a more helpful exception that this one:
Uncaught Error: Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.
I am trying to build a Reagent app without the usual minified React JavaScript library. This is where I have got so far with the project.clj file:
(defproject cljsbin "0.1.0-SNAPSHOT"
:dependencies [
[org.clojure/clojure "1.7.0"]
[compojure "1.1.8"]
[hiccup "1.0.5"]
[ring "1.3.0"]
[ring/ring-json "0.3.1"]
[org.clojure/clojurescript "1.7.48"]
[me.raynes/fs "1.4.6"]
[reagent "0.5.1-rc3"]
;[re-com "0.6.1"]
]
:cljsbuild { :builds [ :optimizations :none]}
:main ^:skip-aot core)
So far I have put the important (is it?) :optimizations :none in a few places in the lein project file, but always the minified React library is included.
Later...
Well I'm now quite sure I should be looking at the artifacts. What :optimizations means is covered here: https://github.com/clojure/clojurescript/wiki/Quick-Start: having optmizations gets rid of the 'goog' is undefined error messages.
So I am now using this:
;[reagent "0.5.1-rc3"]
[reagent "0.5.1-rc3" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "0.13.3-0"]
, which is important because it shows (definitively) that the reagent library includes the react library, and that this react library can be modified. Now just to find out how to get the non-minified version and I'll be able to answer my own question...
Are you sure that once you use the add-ons version, your not already getting the mimified version? I ask as the docs on the cljs/package site say
The externs file includes definitions for TestUtils but to use those with :advanced optimizations you'll need to override :file-min to use non-minified version:
which would indicate that perhaps this uses the non-mimified version unless you use :advanced compilation flag? Perhaps check the externs file and see what it has?
The other solution might be to adopt the approach on the reagent page for using your own build of reagent. To do this, I'm assuming you have to provide a bare bones cljs/react file and add the react js directly into your page?
After updating to qooxdoo 1.5 I am seeing this error:
Uncaught TypeError: Expecting a function in instanceof check, but got #<HTMLDocument>
:8080/qooxdoo-1.5-sdk/framework/source/class/qx/ui/mobile/core/EventHandler.js?nocache=0.38786523090675473:245
Strange thing is, that I am not using the qx.ui.mobile.* classes at all. This is with a source-all build and "qx.debug" set.
As for including the qx.ui.mobile.* classes, this comes from using the source-all job, which includes, well, all known classes, also the qx.ui.mobile.* ones. Try using the normal source job, which only includes the classes necessary for your app.
As for the error, please open a bug report at http://bugzilla.qooxdoo.org. Please specify the OS and browser you are using when you get the error. If possible, supply a minimal Application.js (or a Playground link) that reproduces the error. Cheers.