Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function bound to onChange receives wrong date #226

Closed
janimattiellonen opened this issue Nov 7, 2015 · 25 comments
Closed

Function bound to onChange receives wrong date #226

janimattiellonen opened this issue Nov 7, 2015 · 25 comments

Comments

@janimattiellonen
Copy link

When I select 2015-11-01 the function bound to onChange event gives me "2015-10-31T22:00:00.000Z".

Code used:

<DatePicker
    selected={this.state.startedReading}
    dateFormat="DD.MM.YYYY"
    onChange={::this.handleStartedReadingChange}
/>  

I'm using 0.15.2.

@ryanwilsonperkin
Copy link
Contributor

Sounds like this is likely an issue with confusion between UTC and local time. onChange sends back a momentJS object. I suspect you're doing something like

function handler(newDate) {
  var dateStr = newDate.toString();
}

If so, you can achieve the result you want by first casting to UTC like so:

function handler(newDate) {
  var dateStr = newDate.utc().toString();
}

@janimattiellonen
Copy link
Author

Thanks! Sounds reasonable. I'll try that.

@janimattiellonen
Copy link
Author

Probably my code that errors, but the first time I select a date, the handler gives me the day before. If I select again, a correct date is given.

@ryanwilsonperkin
Copy link
Contributor

Can you post a snippet of your code that's interacting with the datepicker?

@janimattiellonen
Copy link
Author

I stripped the code from unrelated stuff. With this code I still get the weird functionality.


import React, {Component} from 'react';
import DatePicker from 'react-datepicker';

export default class BookForm extends Component {
    constructor(props) {
        super(props);

        this.state = {
            finishedReading: null
        }
    }

    handleFinishedReadingChange(date) {
        console.log("ii: " + date.utc().toString());
        this.setState({
            finishedReading: date.utc().toString(),
        });
    }   

    shouldComponentUpdate(nextProps, nextState) {
        return this.state.id != nextState.id;
    }

    render() {
        return (
            <div className="component">
                <form className="form-horizontal">
                    <div className="form-group">
                        <label htmlFor="finishedReading" className="col-sm-2">Finished reading</label>
                        <div className={'col-sm-8'}>
                            <DatePicker
                                selected={this.state.finishedReading}
                                dateFormat="DD.MM.YYYY"
                                onChange={::this.handleFinishedReadingChange}
                            />  
                        </div>
                    </div>
                </form>
            </div>
        );
    }   
}

@janimattiellonen
Copy link
Author

If I remove shouldComponentUpdate(), I get "t.format is not a function"

@ryanwilsonperkin
Copy link
Contributor

I suspect this is because you're storing finishedReading in your state as a string, rather than a moment object, which is what DatePicker expects for the selected prop. Do you still have the issue if you change your function to:

handleFinishedReadingChange(date) {
    console.log("ii: " + date.utc().toString());
    this.setState({
        finishedReading: date.utc(),
    });
}

@janimattiellonen
Copy link
Author

Even if I remove the call to setState(), I still get the same.

@janimattiellonen
Copy link
Author

If I remove "onChange={this.handleFinishedReadingChange}" then the date is as expected.

@ryanwilsonperkin
Copy link
Contributor

If you remove the onChange event handler, then you are basically allowing the datepicker to simply render it's internal state, ie an uncontrolled component. The date is as expected because the datepicker is handling the moment dates properly internally.

Your shouldComponentUpdate is only updating this component when the id changes, you don't have any references to that in the rest of the snippet you uploaded so I assume it's tied to some other functionality in your app. However, since you're not allowing the component to update you won't be passing in the new value to the datepicker's selected prop.

Can you try something like this:

import React, {Component} from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';

export default class BookForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // Initial value is the current time in UTC
      // Additionally, subsequent moments should all be in UTC now
      finishedReading: moment.utc()
    }
  }

  handleFinishedReadingChange(date) {
    console.log("ii: " + date.toString());
    this.setState({
      finishedReading: date,
    });
  }   

  shouldComponentUpdate(nextProps, nextState) {
    // Test dates instead of id
    // Or, chain a series of needed conditionals
    return this.state.date != nextState.date;
  }

  render() {
    return (
      <div className="component">
        <form className="form-horizontal">
          <div className="form-group">
            <label htmlFor="finishedReading" className="col-sm-2">Finished reading</label>
            <div className={'col-sm-8'}>
              <DatePicker
                selected={this.state.finishedReading}
                dateFormat="DD.MM.YYYY"
                onChange={::this.handleFinishedReadingChange}
              />  
            </div>
          </div>
        </form>
      </div>
    );
  }   
}

@tomdev
Copy link
Member

tomdev commented Nov 11, 2015

+1 @ryanwilsonperkin for helping each other out

@janimattiellonen
Copy link
Author

Apparently setting a proper utc value in constructor "fixed" this. However, I don't want to use a default date.

@ryanwilsonperkin
Copy link
Contributor

@janimattiellonen what happens if you initially pass in null as the value for the selected prop?

@martijnrusschen
Copy link
Member

Did you guys resolve this issue?

@janimattiellonen
Copy link
Author

Sorry, no. I switched to jQuery datepicker :(

@martijnrusschen
Copy link
Member

I'm sorry that we couldn't help you.

@janimattiellonen
Copy link
Author

No problems. Thanks for your time.

@pablolmiranda
Copy link

The problem happens when you pass anything that is not a moment object to DatePicker.selected prop.
I think it will be nice to fix the issue.

@rafeememon
Copy link
Contributor

@pablolmiranda, I'm not sure what there is to fix; passing anything that is neither a moment object nor null is not a supported API.

@pablolmiranda
Copy link

Good point. This is why the 'Clear datepicker input' example is broken.
If you clean the date picker you receive null on the onChange handler, what will break the component internally. After that happens, every single change on the date will be wrong. You will see the date inside the input field correct, but behind the scenes the date object returned in the handler will be incorrect.
Another consequence is, you can not use it as a controlled component and initialize in a empty state.

@rafeememon
Copy link
Contributor

@pablolmiranda taking this discussion to #627

@fay-jai
Copy link

fay-jai commented Dec 3, 2016

I'm also running into the same issue as @janimattiellonen: when I click on a day for the first time, it brings me to the day before. However, when I click on it again, it selects the correct day. Similar to his situation, I want to have an initial state for the date to be undefined because this allows the datepicker to not show a selected date by default.

Is there a workaround for this?

@vladimir-konnov
Copy link

Will duplicate also here from #627 (comment)

Guys, I have the same issue with wrong date.

  1. I scroll months say from June to August.
  2. Then for instance I click 08/01/2017 and get 07/31/2017.

Has anyone found a fix for this issue with wrong date? I'm using react-datepicker v.0.48.0
P.S. Seems that scrolling months is essential

@jessica-branchizio
Copy link

so ummm anyone figure this out @vladimir-konnov?

@VincentHokie
Copy link

This is definitely late but how I ended up getting the correct date was to do something like

handleChange(date) {
  console.log(date) // wrong when we select off the datepicker
  console.log(moment(date.toDate()) // correct date and time
  ...
}

which I found on another issue that I cannot find anymore. I'll link it when I do find it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants