I am importing some React modules from CDN (that's not a requirement, I've also tried with a local build, more in the final question about it):
<script crossorigin src="https://unpkg.com/react-onclickoutside@6.9.0/dist/react-onclickoutside.min.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.0/moment.min.js" integrity="sha512-Izh34nqeeR7/nwthfeE0SI3c8uhFSnqxV0sI9TvTcXiFJkMd6fB644O64BRq2P/LA/+7eRvCw4GmLsXksyTHBg==" crossorigin="anonymous"></script>
<script crossorigin src="https://unpkg.com/react-datepicker@3.1.3/dist/react-datepicker.min.js"></script>
Then I have a script to build the React DatePicker
component, this is the relevant snippet from it:
HelloWorld.Example=function()
{
var p,setCount,count,p$1,c,myDate,datePicker;
p=React$2.useState(0);
setCount=p[1];
count=p[0];
p$1=React$2.useState(new moment(new Date((c=Date.now(),DateUtil.DatePortion(c)))));
myDate=p$1[0];
datePicker=React$2.createElement(DatePicker.default,{
selected:new moment(new Date()),
onChange:p$1[1]
});
React.set_setCount(setCount);
return React$2.createElement("div",null,datePicker,React$2.createElement("p",null,(Html.textf(function($1)
{
The error that I see from the JS Console is:
react-datepicker.min.js:1 Uncaught TypeError: o is not a function
at Ee (react-datepicker.min.js:1)
when the script call ReactDOM.render
.
Is there a way to understand what is o
? Maybe an import missing? ( Edit Well, looking at chrome debugger and comparing it to github , o
is isValidDate
, ie import isValidDate from "date-fns/isValid";
, hence the imports from date-fns
are not working from CDN )
Is there a way such that - for example - I can locally npm run build
the needed module, react-datepicker
, and then call the react API from my script as shown above? (a suggestion that I received was configuring my script as entry in webpack
, but afaik React doesn't use webpack
, though I see it is used in react-datepicker
).
From React docs , I can read that
JSX is not a requirement for using React
so something like the above should be doable, in theory .
I've opened a question/issue on github react-datepicker
repo (in the context of calling this component from WebSharper.React
).
Is there a way such that - for example - I can locally
npm run build
the needed module,react-datepicker
, and then call the react API from my script as shown above?
Yes, there is a well known solution !
Write an index.js as follows
import React from "react";
import DatePicker from 'react-datepicker'
import "react-datepicker/dist/react-datepicker.css";
export {ImportedComponent}
window.MyDatePicker = function MyDatePicker(props) {
console.log("props from window.MyDatePicker", props)
return React.createElement( DatePicker, props );
}
build via npm
and copy the static folder from the build of your by npm run build
to the SPA folder of your proj
copy the 3 script tags from the index.html in the build into the index.html template of your proj and <div id="root"></div>
(of course you use a different id for your project app and there will be nothing to render here)
in my case they are (they will be different for you)
<div id="root"></div>
<script>!function(e){function t(t){for(var n,l,p=t[0],f=t[1],i=t[2],c=0,s=[];c<p.length;c++)l=p[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(a&&a(t);s.length;)s.shift()();return u.push.apply(u,i||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,p=1;p<r.length;p++){var f=r[p];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="/";var p=this.webpackJsonpcontent_npm=this.webpackJsonpcontent_npm||[],f=p.push.bind(p);p.push=t,p=p.slice();for(var i=0;i<p.length;i++)t(p[i]);var a=f;r()}([])</script>
<script src="/static/js/2.a6e4c224.chunk.js"></script>
<script src="/static/js/main.b075c560.chunk.js"></script>
Now go with
datePicker=React$1.createElement(window.MyDatePicker,{
selected:myDate,
onChange:p$1[1],
showTimeSelect: true,
});
in you SPA.js and enjoy any react component like this one from WebSharper.React !
Btw I had to pass a JS date, not a Moment date here in the selected
of props
, I'm not sure why, anyway, this is not relevant to the problem.
FYI, this is the F# code from WebSharper project
let myDate, setMyDate = WrapReact.UseState (DateTime.Today.JS)
let importDatePicker = JS.Eval("window.MyDatePicker") :?> React.Class
let propDP =
{
selected = myDate
onChange = setMyDate
showTimeSelect = true
}
let datePicker =
React.CreateElement( importDatePicker, propDP)
WrapReact.setCount <- setCount
div [] [
datePicker
p [] [Html.textf "You selected %s date %s time" (myDate.ToDateString()) (myDate.ToTimeString())]
Full open source project shared on github .
I think that the main problem is that WebSharper scripts are not JavaScript modules . In that case it should be immediate to import an external module or make the above SPA.js
as the Webpack
main entry. In fact it is well known that there are differences between <script type=module>
and <script>
As confirmed by Adam Granicz indeed on WebSharper side:
that should be the way, yes, @Jand42 and others have been working on changing the current output to support modules and a better TS interoperability - this has been on the agenda for years, so closing it would be a good step forward
(In the meantime there are of course alternatives, eg flatpickr , which has bindings also for jQuery, instead of react-datepicker
or pure React or F# Fable instead of WebSharper.React and so on)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.