Reputation: 3044
I have a DatePicker parent component that has a child SearchBar component. The SearchBar is an input that has an onChange, which is connected to DatePicker's handleSearchChange. The SearchBar will initialize with the current Date plugged in due to DatePicker passing its state of currentDateObj down. However, SearchBar's input should change from user input because it's onChange will change the state of DatePicker, which should in turn change SearchBar's input, but even with my console.logs I don't see SearchBar being re-rendered and the input keeps resetting itself to the initial date (today) rather than showing any change to user input.
//DatePicker
var DatePicker = React.createClass({
getInitialState: function () {
var today = new Date();
return {currentDateObj: today, searchInput: undefined};
},
handleSearchChange: function (e) {
var inputString = e.target.value.toString();
var inputRegex = /^\d{2}[/]\d{2}[/]\d{4}$/;
if (inputRegex.test(inputString)) {
var year = e.target.value[6]+e.target.value[7]+e.target.value[8]+e.target.value[9];
var month = e.target.value[0]+e.target.value[1];
var day = e.target.value[3]+e.target.value[4];
var currentDateObj = new Date(year, month, day);
this.setState({currentDateObj:currentDateObj });
} else {
this.setState({searchInput: inputString});
}
},
render: function () {
var datePickerComponent = this;
var dateNextYearObj = new Date();
var searchDateObj = this.state.searchInput === undefined ? this.state.currentDateObj : this.state.searchInput;
console.log('hit datepick render');
console.log(this.state.searchInput);
dateNextYearObj.setFullYear(this.state.currentDateObj.getFullYear() + 1);
return(
<div>
<SearchBar currentDateObj={searchDateObj} handleSearchChange={this.handleSearchChange}/>
</div>
);
}
});
//SearchBar
var SearchBar = React.createClass({
getInitialState: function () {
console.log('hit searchbar render')
var currentDateObj = this.props.currentDateObj;
if(typeof (currentDateObj.getMonth) === "function"){
var currentDate = currentDateObj.getDate().toString();
if (currentDate.length === 1) {currentDate = "0" + currentDate;}
var currentMonth = currentDateObj.getMonth().toString();
if (currentMonth.length === 1) {currentMonth = "0" + currentMonth;}
var currentYear = currentDateObj.getFullYear().toString();
var formattedCurrentDate = currentMonth + "/" + currentDate + "/" + currentYear;
return {currentDateObj: formattedCurrentDate};
} else {
return {currentDateObj: currentDateObj};
}
},
render: function () {
return (
<div>
<input type="text" onChange={this.props.handleSearchChange} value={this.state.currentDateObj}/>
</div>
);
}
});
Upvotes: 0
Views: 721
Reputation: 487
The getIntialState method is only invoked once when your component is first created so it will not be useful on subsequent renders.
You might want to stick the formatting logic somewhere else such as the render function or a more convenient lifecycle method such as componentWillReceiveProps, which is the way I would do it. Let me know if that helps and best of luck.
No longer relevant due to Autobind by Default
You are likely losing your this
binding when passing down the handler. Try this:
<SearchBar currentDateObj={searchDateObj} handleSearchChange={this.handleSearchChange.bind(this)}/>
Check out all the cool ways you can manage your bindings in this blog by Igor Smirnov. I use Babel to transpile my code and with the stage-0
preset, I can simply use fat arrow functions in my class handler methods so I never have to worry about this
.
Upvotes: 3
Reputation: 356
Try binding the keyword this to your handleSearchChange function.
<SearchBar currentDateObj={searchDateObj} handleSearchChange={this.handleSearchChange.bind(this)}/>
<input type="text" onChange={this.props.handleSearchChange.bind(this)} value={this.state.currentDateObj}/>
If you're getting an error like 'Cannot read property 'setState' of null, binding this to your function should fix the error.
Upvotes: 1