javascriptreactjsf#react-datepickerwebsharper

Creating a DatePicker from CDN with React API


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, i.e. 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).


Solution

  • 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.