mui / material-ui-pickers

Date & Time pickers for Material UI (support from v1 to v4)
https://github.com/mui/material-ui-pickers/issues/2157
MIT License
2.32k stars 833 forks source link

problem with date-fns #240

Closed soroushm closed 6 years ago

soroushm commented 6 years ago

Environment

Tech Version
material-ui-pickers material-ui-pickers@^1.0.0-rc.1
material-ui material-ui@1.0.0-beta.21
React react@15.6.1
date-fns date-fns@1.29.0
Browser any
Platform osx

Steps to reproduce

  1. Update date picker
  2. get date-fns error
  3. npm install date-fns
  4. get error like this
    ./~/material-ui-pickers/utils/date-fns-utils.js
    Module not found: Can't resolve 'date-fns/addDays'

date-fns have folder like add_days

Expected behavior

import parse from 'date-fns/parse'; import addDays from 'date-fns/add_days'; import addMonths from 'date-fns/add_months'; import addYears from 'date-fns/add_years'; import endOfDay from 'date-fns/end_of_day'; import endOfMonth from 'date-fns/end_of_month'; import endOfWeek from 'date-fns/end_of_week'; import endOfYear from 'date-fns/end_of_year'; import format from 'date-fns/format'; import isAfter from 'date-fns/is_after'; import isBefore from 'date-fns/is_before'; import isSameDay from 'date-fns/is_same_day'; import isValid from 'date-fns/is_valid'; import setDay from 'date-fns/set_day'; import setHours from 'date-fns/set_hours'; import setMinutes from 'date-fns/set_minutes'; import setYear from 'date-fns/set_year'; import startOfDay from 'date-fns/start_of_day'; import startOfMonth from 'date-fns/start_of_month'; import startOfWeek from 'date-fns/start_of_week'; import startOfYear from 'date-fns/start_of_year'; import getHours from 'date-fns/get_hours'; import getYear from 'date-fns/get_year'; import isEqual from 'date-fns/is_equal';

Actual behavior

import parse from 'date-fns/parse'; import addDays from 'date-fns/addDays'; import addMonths from 'date-fns/addMonths'; import addYears from 'date-fns/addYears'; import endOfDay from 'date-fns/endOfDay'; import endOfMonth from 'date-fns/endOfMonth'; import endOfWeek from 'date-fns/endOfWeek'; import endOfYear from 'date-fns/endOfYear'; import format from 'date-fns/format'; import isAfter from 'date-fns/isAfter'; import isBefore from 'date-fns/isBefore'; import isSameDay from 'date-fns/isSameDay'; import isValid from 'date-fns/isValid'; import setDay from 'date-fns/setDay'; import setHours from 'date-fns/setHours'; import setMinutes from 'date-fns/setMinutes'; import setYear from 'date-fns/setYear'; import startOfDay from 'date-fns/startOfDay'; import startOfMonth from 'date-fns/startOfMonth'; import startOfWeek from 'date-fns/startOfWeek'; import startOfYear from 'date-fns/startOfYear'; import getHours from 'date-fns/getHours'; import getYear from 'date-fns/getYear'; import isEqual from 'date-fns/isEqual';

and now get a new error

React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.

Check the render method of `ModalWrapper`.
SignUp
src/components/person/SignUp.js:112
  109 | {/*leftArrowIcon={<KeyboardArrowLeft />}*/}
  110 | {/*rightArrowIcon={<KeyboardArrowRight />}*/}
  111 | 
> 112 | <DatePicker
  113 |     keyboard
  114 |     clearable
  115 |     label="Choose a date"
View compiled
SignUp
src/components/person/SignUp.js:49
  46 | switch(step){
  47 |  case 0:
  48 |      return (
> 49 |          <div>
  50 |              <TextField
  51 |                  required
  52 |                  id="required"
View compiled
SignUp
src/components/person/SignUp.js:185
  182 | <Step key={label}>
  183 |     <StepLabel>{label}</StepLabel>
  184 |     <StepContent>
> 185 |         <Typography>{getStepContent(index, classes, this.state, this.handleChange)}</Typography>
  186 |         <div className={classes.actionsContainer}>
  187 |             <div>
  188 |                 <Button
View compiled
SignUp
src/components/person/SignUp.js:182
  179 | <Stepper activeStep={activeStep} orientation="vertical">
  180 |     {steps.map((label, index) => {
  181 |         return (
> 182 |             <Step key={label}>
  183 |                 <StepLabel>{label}</StepLabel>
  184 |                 <StepContent>
  185 |                     <Typography>{getStepContent(index, classes, this.state, this.handleChange)}</Typography>
View compiled
SignUp
src/components/person/SignUp.js:179
  176 |      justify="center">
  177 | <Grid item xs={12} sm={6} md={4}>
  178 |     <Paper className={classes.paper}>
> 179 |         <Stepper activeStep={activeStep} orientation="vertical">
  180 |             {steps.map((label, index) => {
  181 |                 return (
  182 |                     <Step key={label}>
View compiled
SignUp
src/components/person/SignUp.js:172
  169 | 
  170 | return (
  171 |     <div className={classes.container}>
> 172 |         <Grid container
  173 |               className={classes.fullHeight}
  174 |               alignItems="center"
  175 |               direction="row"
View compiled
PP
src/components/common/Container.js:102
   99 | <section
  100 |     className={classNames(classes.content, open && classes.contentShift)}
  101 | >
> 102 |     <WrappedComponent {...this.props} {...newProps}/>
  103 |     <AddCompanyDialog
  104 |         open={this.state.AddCompany}
  105 |         handleClose={() =>this.setState({AddCompany: false})}
View compiled
PP
src/components/common/Container.js:99
   96 |         </List>
   97 |     </div>
   98 | </Drawer>
>  99 | <section
  100 |     className={classNames(classes.content, open && classes.contentShift)}
  101 | >
  102 |     <WrappedComponent {...this.props} {...newProps}/>
View compiled
PP
src/components/common/Container.js:74
  71 | 
  72 | return (
  73 |  <MuiThemeProvider theme={theme}>
> 74 |      <div className={classes.appFrame}>
  75 |          <Helmet htmlAttributes={this.htmlAttr()} bodyAttributes={{class: `page_${name}`}}/>
  76 |          <Header {...this.props} title={name} open={open} drawer={this.handleDrawerToggle}/>
  77 |          <Drawer
View compiled
Route
src/routes.js:28
  25 | 
  26 | renderSignUp = (props) =>{
  27 |     this.handleAuthentication(props);
> 28 |     return <SignUp {...props} />
  29 | }
  30 | 
  31 | setSession(authResult){
View compiled
CustomeRoutes
src/routes.js:77
  74 | <Route path="/entity/:entityname" component={Entity}/>
  75 | <Route path="/flow/:username" component={Flow}/>
  76 | <Route path="/skill/:id" component={Skill}/>
> 77 | <Route path="/signUp" render={this.renderSignUp}/>
  78 | <Route path="/error"
  79 |        render={() => <h1>Something went wrong! please try again later!</h1>}/>
  80 | <Route path="*" render={() => <h1>Not found</h1>}/>
View compiled
CustomeRoutes
src/routes.js:71
  68 | <MuiPickersUtilsProvider utils={MomentUtils}>
  69 |     <JssProvider jss={jss}>
  70 |         <Router>
> 71 |             <Switch>
  72 |                 <Route exact path="/" component={Landing}/>
  73 |                 <Route path="/person/:username" component={Personal}/>
  74 |                 <Route path="/entity/:entityname" component={Entity}/>
View compiled
CustomeRoutes
src/routes.js:68
  65 | <ApolloProvider client={client}>
  66 |     <Provider store={store}>
  67 |         <I18nextProvider i18n={ i18n }>
> 68 |             <MuiPickersUtilsProvider utils={MomentUtils}>
  69 |                 <JssProvider jss={jss}>
  70 |                     <Router>
  71 |                         <Switch>
View compiled
CustomeRoutes
src/routes.js:65
  62 | const jss = create({plugins: [...preset().plugins, rtl()]});
  63 | jss.options.createGenerateClassName = createGenerateClassName;
  64 | return (
> 65 |   <ApolloProvider client={client}>
  66 |       <Provider store={store}>
  67 |           <I18nextProvider i18n={ i18n }>
  68 |               <MuiPickersUtilsProvider utils={MomentUtils}>
View compiled
(anonymous function)
src/index.js:11
   8 | import CustomeRoutes from './routes';
   9 | 
  10 | render(
> 11 |   <CustomeRoutes />
  12 |   , document.getElementById('root')
  13 | );
  14 | registerServiceWorker();
dmtrKovalenko commented 6 years ago

You need date fns 2.0 Install it like npm i date-fns@next

soroushm commented 6 years ago

@dmtrKovalenko Please add npm install date-fns@next -S in Documentation in Installation Section

andrew-w-ross commented 6 years ago

@dmtrKovalenko Why not add date-fns as a peer dependency? At least then yarn would complain.

dmtrKovalenko commented 6 years ago

@andrew-w-ross Because we have a dependency moment OR date-fns

soroushm commented 6 years ago

@dmtrKovalenko Thank you for added in docs

aeroxy commented 5 years ago

Still won't work:

import error: 'DateFnsUtils' is not exported from 'date-fns'.

Please add document about how to use date-fns with @material-ui/pickers

Also, since moment won't work with @material-ui/pickers, why not just add date-fns into the package itself.

pharingee commented 5 years ago

You need to install both date-fns@next and @date-io/date-fns to get it to work.

$ npm i --save date-fns@next @date-io/date-fns
dmtrKovalenko commented 5 years ago

@aeroxy I'll try to describe everything

1) You really need to install both @date-io/date-fns and date-fns@next 2) This library supports moment users. For moment you will need to install @date-io/moment and moment. Instead of date-fns respectively. 3) We are not adding the date-fns directly to the package in order to make possible to use moment, dayjs or luxon. But date-fns is recommended and primarily supported lib.

aeroxy commented 5 years ago

I see. But this is confusing. Why not just, again, add date-fns into the package itself. You can add another npm package called material-ui-pickers-pure or material-ui-pickers-bare without date-fns libs.

vonkanehoffen commented 5 years ago

Yeah I don't really get the thinking behind having the provider in general. Having to wrap everything in <MuiPickersUtilsProvider utils={DateFnsUtils}> makes no sense. Better to pull the required date-fns as a dependency of the component. Cleaner code and better DX.

armenr commented 5 years ago

We got bit by this. We lost considerable time trying to understand the what and the why of this.

My team and I are in full support of @aeroxy 's suggestion.

dmtrKovalenko commented 5 years ago

We will not get out of current solution at least for now You need to wrap the component only 1 time. A lot of developers using moment (60%) but a lot of users don't want to. This is the only solution for that