I have a JSX component that returns a React component:
import React from "react";
import Select from "react-select";
import Survey from "survey-react";
const CustomSearchWidget = ({ choices, onChange }) => {
...
return (
<Select
...
/>
);
};
export const SearchWidget = {
...
render: (question) => {
return (
<CustomSearchWidget
...
/>
);
},
};
When I compile this using babel with npx babel *.jsx --out-dir gen
and import this compiled file in a clojurescript file like so:
["./surveyjs/widgets/gen/SearchWidget.js" :refer [SearchWidget]]
and use the SearchWidget in the application I get this error:
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object
If I return <div/>
instead of <Select/>
this error does not occurIs there a workaround for this?
@erwinrooijakkers you ...
out a bunch of code so I cannot see what this SearchWidget
actually is. from what you left in it is not a correct react component and that is what the error is telling you?
maybe you just forgot a export const SearchWidget = class extends React.Component {
?
Full code:
import React from "react";
import Select from "react-select";
import Survey from "survey-react";
const CustomSearchWidget = ({ choices, onChange }) => {
const handleChange = (option) => {
onChange(option.value);
};
const options = choices.map((choice) => {
return { label: choice, value: choice };
});
return (
<Select
className="basic-single"
classNamePrefix="select"
isClearable={true}
isSearchable={true}
name="color"
options={options}
onChange={handleChange}
/>
);
};
export const SearchWidget = {
name: "search dropdown",
title: "Dropdown with search",
isFit: function (question) {
return question.getType() === "searchdropdown";
},
activatedByChanged: function (activatedBy) {
Survey.JsonObject.metaData.addClass("searchdropdown", [], null, "text");
Survey.JsonObject.metaData.addProperties("searchdropdown", [
{ name: "choices", default: ["Click Me"] },
]);
},
render: (question) => {
return (
<CustomSearchWidget
choices={question.choices}
placeholder={question.title}
onChange={(val) => (question.value = val)}
/>
);
},
};
Thank you. I added the full code in the reply
export const SearchWidget = class extends React.Component {
gives babel compilation error:
Unexpected token (28:6)
26 |
27 | export const SearchWidget = class extends React.Component {
> 28 | name: "search dropdown",
| ^
with npx babel *.jsx --out-dir gen
these are functional components I understand from the party that helped made them, so cannot add a class extends React.Component, although they say in the end itβs the same
(And it goes wrong when importing like so):
(ns nl.mediquest.questionnaire-frontend.component.survey
(:require
["./surveyjs/widgets/gen/SearchWidget.js" :refer [SearchWidget]]
[survey-react :refer [Survey StylesManager CustomWidgetCollection]]))
(.. CustomWidgetCollection -Instance (addCustomWidget SearchWidget "customtype"))
package.json
{
"devDependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.14.6",
"@babel/plugin-transform-react-jsx": "^7.14.5",
"shadow-cljs": "2.10.12"
},
"dependencies": {
"@fortawesome/fontawesome-pro": "^5.13.0",
"@fullhuman/postcss-purgecss": "^2.0.5",
"autoprefixer": "9.8.0",
"global": "^4.4.0",
"postcss-cli": "7.1.1",
"postcss-import": "^12.0.1",
"react": "^16.13.0",
"react-dom": "16.13.0",
"react-select": "^4.3.1",
"recharts": "1.8.5",
"survey-react": "^1.8.4",
"tailwindcss": "1.4.6"
},
"scripts": {
"build-css": "node_modules/postcss-cli/bin/postcss resources/public/css/tailwind.css -o resources/public/style.css"
}
it is something with the Select
component, because when I turn it into <div/>
the webpage renders and there are no errors
as the error is telling you an object is not a valid react component
so whatever it is it is invalid. it has nothing to do with shadow-cljs, it is purely a react error
maybe its meant to be a React.createClass({ name: ...})
I fixed it by changing:
import Select from "react-select";
to
const Select = require('react-select');
the same code did work in javascript for some reason
in the create-react-app
anyway
thanks for the help!
via https://github.com/facebook/react/issues/13445#issuecomment-595470399
I'm using shadow-cljs, with the helix library.
I'm noticing that a tagged js literal such as #js []
when placed anywhere within the form of a call to react/useState, breaks the hooks state preservation on hot reload.
For example test-state
is preserved if I make a code change with this component:
(defnc test-component []
(let [[test-state set-test-state] (react/useState (do [] 1))]
($ "button" {:on-click #(set-test-state inc)} (str "test1: " test-state))))
but if I tag the array inside the do form with a #JS like the following, the state of test-state is not preserved if I make a code change:
(defnc test-component []
(let [[test-state set-test-state] (react/useState (do #js [] 1))]
($ "button" {:on-click #(set-test-state inc)} (str "test1: " test-state))))
maybe this is not a shadow-cljs issue, but any help would be much appreciated, thanks!why is there a do
in the first place?
but yeah not a shadow-cljs issue. that is either helix or react, don't know
helik π
simply to demonstrate that it's some sort of reader issue. The empty array never even reaches react/useState only the '1' does.
maybe helix does some stuff in a macro. I don't really know how hot-reload works with hooks. I would assume useState
is always lost, just like local state is normally lost. given that component type changes it should go through a full unmount/mount cycle
the weird thing is it seems to be related to the tagged literal. If I write
(defnc test-component []
(let [a #js []
[test-state set-test-state] (react/useState (do a 1))]
($ "button" {:on-click #(set-test-state inc)} (str "test1: " test-state))))
it works fineAnd this works fine also
(defnc test-component []
(let [[test-state set-test-state] (react/useState (do (array) 1))]
($ "button" {:on-click #(set-test-state inc)} (str "test1: " test-state))))
that's what makes me think it's either clojurescript or shadowreally need to ask in the #helix channel. I don't have a clue what defnc
does internally
ok thanks very much π
just a glance at the macro code makes me pretty certain that it is the macro
https://github.com/lilactown/helix/blob/master/src/helix/core.clj#L170
not shadow or cljs
ah brilliant, that's very helpful, I guess it's analysing the code for calls to react hooks and something about the tagged literal is tripping it up, cheers