提交表单时如何使用异步调用呈现ReactJS组件(仅一次)?

时间:2018-05-09 09:15:27

标签: javascript reactjs

我正在创建一个搜索电影的应用。现在一切都在一个班级。我想制作一部电影"我搜索电影时只渲染一次的组件。电影渲染时我对OMDB进行了异步调用。我只希望这发生一次,只有当我点击搜索按钮时才会发生。

到目前为止,我有它工作,只有ReactJS一遍又一遍地渲染Movie组件,这意味着我的应用程序不断将API调用发送到OMDB数据库。这是我的代码:

import React, { Component } from 'react';
import { BrowserRouter as Router, Link, NavLink } from 'react-router-dom';
import Route from 'react-router-dom/Route';

import './App.css';

import language from './Components/Language';
import Navbar from './Components/Navbar';
import NavbarSimple from './Components/NavbarSimple';

class App extends Component {
  constructor(){
    super();

    this.state = {
      movieSearchTerm: '',
      error: '',
      languageIndex: 0,
      searchSubmitted: false,

      title: "",
      year: "",
      rated: "",
      released: "",
      runtime: "",
      genre: "",
      director: "",
      writer: "",
      actors: "",
      plot: "",
      language: "",
      awards: "",
      poster: "",
      list_ratings: "",
      imdbRating: "",
      imdbVotes: "",
      type: ""
    }

    this.onChangeMovieInput = this.onChangeMovieInput.bind(this);
    this.onSubmitMovieForm = this.onSubmitMovieForm.bind(this);
    this.switchLanguageTo = this.switchLanguageTo.bind(this);

    this.setSearchSubmittedTo = this.setSearchSubmittedTo.bind(this);
  }

  switchLanguageTo(id){
    this.setState({
      languageIndex: id
    });
  }

  getMovie(title){
    console.log("Searching movie '" + title + "'");
    var xhr = new XMLHttpRequest();
    var json_obj, status = false;
    xhr.open("GET", "http://www.omdbapi.com/?t=" + title + "&apikey=6c3a2d45", true);
    xhr.onload = function (e) {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          var movie = JSON.parse(xhr.responseText);
          status = true;
          console.log(movie);
          if(movie.Error){
            this.setState({
              error: movie.Error
            });
          } else {
            this.setState({
              title: movie.Title,
              year: movie.Year,
              rated: movie.Rated,
              released: movie.Released,
              runtime: movie.Runtime,
              genre: movie.Genre,
              director: movie.Director,
              writer: movie.Writer,
              actors: movie.Actors,
              plot: movie.Plot,
              language: movie.Language,
              awards: movie.Awards,
              poster: movie.Poster,
              // list_ratings: movie.Ratings // Need to come up with a solution to render arrays as csv.
              imdbRating: movie.imdbRating,
              imdbVotes: movie.imdbVotes,
              type: movie.Type
            });
          }
        } else {
          console.log(xhr.status + ": " + xhr.statusText);
        }
      }
    }.bind(this);
    xhr.onerror = function (e) {
      console.log(xhr.status + ": " + xhr.statusText);
    };
    xhr.send(null);
  }

  onChangeMovieInput(e){
    this.setState({
      movieSearchTerm: e.target.value
    })
  }

  onSubmitMovieForm(e){
    e.preventDefault();
    console.log("Movie to be searched: " + this.state.movieSearchTerm);
    this.setState({searchSubmitted: true});
    // this.getMovie(this.state.movieSearchTerm);
  }

  setSearchSubmittedTo(value){
    this.setState({searchSubmitted: value});
  }

  render() {
    if(this.state.searchSubmitted === false){
      return (
        <div>
          <Navbar languageIndex={this.state.languageIndex} switchTaal={this.switchLanguageTo} />
          <div className="App container-fluid mt-large">

            {/* START SEARCH COMPONENT */}
            <div className="row">
              <div className="col-xs-12">
                <form onSubmit={this.onSubmitMovieForm}>
                  <input type="text" className="width-100p" onChange={this.onChangeMovieInput} />
                  <button type="submit" className="width-100p btn btn-primary">Search</button>
                </form>
              </div>
            </div>
            {/* EINDE SEARCH COMPONENT */}

            <div className="row">

              {/* START MOVIE COMPONENT */}
              <div className="movie">
                <div className="row">
                  <div className="col-xs-12">
                    <p>{language[this.state.languageIndex].searchMovieInstruction} <span className={this.state.error===""?"hidden":"visible"}>Error: {this.state.error}</span></p>
                  </div>
                </div>
              </div>
              {/* EINDE MOVIE COMPONENT */}

            </div>
          </div>
        </div>
      );
      // EINDE RETURN
    } else {
      return (
        <div>
          <Navbar languageIndex={this.state.languageIndex} switchTaal={this.switchLanguageTo} />
          <div className="App container-fluid mt-large">

            {/* START SEARCH COMPONENT */}
            <div className="row">
              <div className="col-xs-12">
                <form onSubmit={this.onSubmitMovieForm}>
                  <input type="text" className="width-100p" onChange={this.onChangeMovieInput} />
                  <button type="submit" className="width-100p btn btn--primary">Search</button>
                </form>
              </div>
            </div>
            {/* EINDE SEARCH COMPONENT */}

            <div className="row">

{/* I WANT THIS COMPONENT TO RENDER AS "<Movie title={this.state.movieSearchTerm} /> only when I click on search. The movie component then makes a call to the OMDB resulting in the search result. */}

              {/* START MOVIE COMPONENT */}
              <div className="movie">
                <div className="row">
                  <div className="col-xs-12 col-sm-3 col-md-2">
                    <img src={this.state.poster} className="img-responsive movie--image" />
                  </div>
                  <div className="col-xs-12 col-sm-9 col-md-10">
                    <div className="flex flex-justify-between flex-align-center">
                      <div className="flex-padding-left">
                        <h3>{this.state.title} <span style={{textTransform:'capitalize'}}>{"(" + this.state.type}</span> - {this.state.year + ")"}</h3>
                      </div>
                      <div className="flex-padding-right">
                        Rating
                      </div>
                    </div>

                    <div className="row">
                      <div className="col-xs-12">
                        <p className="text--subtext">{this.state.runtime} | {this.state.genre} | {this.state.released}</p>
                      </div>
                    </div>
                    <div className="row">
                      <div className="col-xs-12 mt-small">
                        {this.state.plot}
                      </div>
                    </div>
                    <div className="row">
                      <div className="col-xs-12 col-sm-6">
                        <ul className="list">
                          <li>Director: {this.state.director}</li>
                          <li>Writer: {this.state.writer}</li>
                          <li>Language: {this.state.language}</li>
                          <li>Actors: {this.state.actors}</li>
                        </ul>
                      </div>
                    </div>
                    <div className="row">
                      <div className="col-xs-12 box">
                        List of ratings
                      </div>
                    </div>
                    <div className="row">
                      <div className="col-xs-12 box">
                        Awards
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              {/* EINDE MOVIE COMPONENT */}

            </div>
          </div>
        </div>
      );
      // EINDE RETURN
    }
  }

  isEmpty(variable){return (variable == "" || variable === "" || variable == undefined || variable === undefined || variable == null || variable === null) == true;}
}

export default App;

如果有任何不清楚的地方,请告诉我,我会在有空的时候更新我的帖子。

0 个答案:

没有答案