简体   繁体   中英

react parent not re-rendering child despite state change

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>
    );
  }
});

Revised Answer

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.


Resources


Old answer:

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 .

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM