简体   繁体   中英

React Tutorial and Sinatra API: Uncaught TypeError: this.props.data.map is not a function

I know, there are hundreds of questions with the same title, but nothing helped my get a solution for my problem. so I worked through the official react js tutorial and build a small API with sinatra to test things.

so everything works really good. except of one error I see in the console when submitting a new "Joke" (called them jokes instead of comments ;)) via AJAX.

app.js:66 Uncaught TypeError: this.props.data.map is not a function

This happens when I click on submit. I logged the state when submitting the form and everything seems to be okay (array with the temporary objects).

so the new Joke is being added and written to the database. It works but i don't know why I'm getting the Uncaught TypeError in the console.

thanks in advance!

var JokeBox = React.createClass({
  loadJokesFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleJokeSubmit: function(joke) {
    var jokes = this.state.data;
    var tmpJoke = jQuery.extend({}, joke)
    tmpJoke.id  = new Date();
    tmpJoke.likes = 0;
    jokes.unshift(tmpJoke);
    this.setState({data: jokes}, function(){
      $.ajax({
        url: this.props.url,
        dataType: 'json',
        type: 'POST',
        data: joke,
        success: function(data) {
          this.setState({data: data});
        }.bind(this),
        error: function(xhr, status, err) {
          this.setState({data: jokes});
          console.error(this.props.url, status, err.toString());
        }.bind(this)
      });
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadJokesFromServer();
    setInterval(this.loadJokesFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      <div className="jokes">
        <h1>Jokes</h1>
        <JokeForm onJokeSubmit={this.handleJokeSubmit} />
        <JokeList data={this.state.data} />
      </div>
    );
  }
});

var JokeList = React.createClass({
  render: function() {
    var jokeNodes = this.props.data.map(function(joke) {
      return (
        <Joke content={joke.content} key={joke.id} likes={joke.likes} />
      );
    });
    return (
      <div className="jokeList">
        {jokeNodes}
      </div>
    );
  }
});

var JokeForm = React.createClass({
  getInitialState: function() {
    return {content: ''};
  },
  handleContentChange: function(e) {
    this.setState({content: e.target.value});
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var content = this.state.content.trim();
    if (!content) {
      return;
    }
    this.props.onJokeSubmit({content: content});
    this.setState({content: ''});
  },
  render: function() {
    return (
      <form className="jokesForm" onSubmit={this.handleSubmit}>
        <input
          type="text"
          placeholder="Your Joke!"
          value={this.state.content}
          onChange={this.handleContentChange}
        />
        <input type="submit" value="Send joke" />
      </form>
    );
  }
});

var Joke = React.createClass({
  render: function() {
    return (
      <div className="joke">
        <p className="jokeContent">{this.props.content}</p>
        <p className="jokeLikes">{this.props.likes}</p>
      </div>
    );
  }
});

ReactDOM.render(
  <JokeBox url="/api/jokes" pollInterval={2000} />,
  document.getElementById('app')
);

// EDIT

So I played around with the sample tutorial repo from the tutorial. I log the data in the handleSubmit in the success function right before the state is set. And I figured out: my data is ja object of the actual new Joke, in the sample tutorial it is an array of all comments. How could this be? I can't find my mistake...

try

handleJokeSubmit: function(joke) {

    let {data}= this.state;

    $.post(this.props.url, joke, res=>{
       this.setState({data:[res,...data]});
    })
   .fail( err=>alert('Error: ' + err.responseText));
}

///EDIT es5

handleJokeSubmit: function(joke) {

    var data = this.state.data;

    $.post(this.props.url, joke, function(res){
       this.setState({data:[res].concat(data)});
    }.bind(this))
   .fail( function(err){alert('Error: ' + err.responseText)});
}

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