React setState fetch API

时间:2017-12-29 19:34:21

标签: reactjs fetch-api setstate

我现在开始学习React并创建我的第二个项目。我正在尝试使用MovieDb API来创建一个电影搜索应用程序。当我得到最初的电影列表时,一切都很好。但是点击每个列表项我想要显示每部电影的细节。我使用vanilla JS和传统的XHR调用创建了一些这样的应用程序。这次我使用fetch API,这似乎很简单,只是使用,但是当我通过响应数据映射来获取每部电影的id以便为每个电影单独检索细节时,我得到所有项目的详细信息的完整列表,这不是理想的效果。我把对象列表放到一个数组中,因为在map中的setState之后我只得到了最后一个元素的细节。我知道我可能在API调用中做错了,但它可能也是我的整个REACT代码。我将不胜感激任何帮助。

我的代码

App.js

import React, { Component } from 'react';
import SearchInput from './Components/SearchInput'
import './App.css';

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

      this.state = 
        {
          value: '',
          showComponent: false, 
          results: [],
          images: {},
        };

    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleOnChange = this.handleOnChange.bind(this);
    this.getImages = this.getImages.bind(this);
    this.getData = this.getData.bind(this);
}

ComponentWillMount() {
  this.getImages();
  this.getData();
}

getImages(d) {
  let request = 'https://api.themoviedb.org/3/configuration?api_key=70790634913a5fad270423eb23e97259'
  fetch(request)
    .then((response) => {
        return response.json();
    }).then((data) => {
      this.setState({
        images: data.images
      });
    });
}

  getData() {
    let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.state.value+'');

    fetch(request)
      .then((response) => {
        return response.json();
      }).then((data) => {               
        this.setState({
          results: data.results
        });             
      });
  }

  handleOnChange(e) {
    this.setState({value: e.target.value})
  }

  handleSubmit(e) {
    e.preventDefault();
    this.getImages();
    this.setState({showComponent: true});
    this.getData();
  }

  render() {
    return (
      <SearchInput handleSubmit={this.handleSubmit} handleOnChange={this.handleOnChange} results={this.state.results} images={this.state.images} value={this.state.value} showComponent={this.state.showComponent}/>
    );
  }
}

export default App;


SearchInput.js

import React, {Component} from 'react';
import MoviesList from './MoviesList';

class SearchInput extends Component {
  render() {
    return(
      <div className='container'>
        <form id='search-form' onSubmit={this.props.handleSubmit}>
          <input value={this.props.value} onChange={this.props.handleOnChange} type='text' placeholder='Search movies, tv shows...' name='search-field' id='search-field' />
          <button type='submit'>Search</button>
        </form>
        <ul>
          {this.props.showComponent ?
              <MoviesList value={this.props.value} results={this.props.results} images={this.props.images}/> : null
          }
        </ul>
      </div>
    )
  }
}

export default SearchInput;

这是我尝试获取详细信息数据的组件

MovieList.js

import React, { Component } from 'react';
import MovieDetails from './MovieDetails';

let details = [];

class MoviesList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showComponent: false,
      details: []
    }

    this.showDetails = this.showDetails.bind(this);
    this.getDetails = this.getDetails.bind(this);

  }


  componentDidMount() {
    this.getDetails();
  }

  getDetails() {
    let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');

    fetch(request)
      .then((response) => {
        return response.json();
      }).then((data) => {    
      data.results.forEach((result, i) => {
        let url = 'https://api.themoviedb.org/3/movie/'+ result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
        return fetch(url)
        .then((response) => {
          return response.json();
        }).then((data) => {
          details.push(data)   
          this.setState({details: details});   
        });
      });   
      console.log(details);
  });
}



  showDetails(id) {
    this.setState({showComponent: true}, () => {
      console.log(this.state.details)
    });
    console.log(this.props.results)
  }

  render() {
    let results;
    let images = this.props.images;

    results = this.props.results.map((result, index) => {
      return(
        <li ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
          {result.title}{result.id}
          <img  src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
        </li>
      )
    });

    return (
      <div>
        {results}
        <div>
          {this.state.showComponent ? <MovieDetails details={this.state.details} results={this.props.results}/> : null}
        </div>
      </div>
    )
  }
}

export default MoviesList;

MovieDetails.js

import React, { Component } from 'react';

class MovieDetails extends Component {


  render() {
    let details;
    details = this.props.details.map((detail,index) => {
      if (this.props.results[index].id === detail.id) {
      return(
        <div key={detail.id}>
          {this.props.results[index].id}  {detail.id}
        </div>
      )} else {
        console.log('err')
      }
    });

    return(
      <ul>
        {details}
      </ul>
    )

  }
}

export default MovieDetails;

2 个答案:

答案 0 :(得分:1)

这里有很多事情......

//在这里你会附上一个onclick监听器,如果你愿意,可以通过其中一个,id或完整结果发送你的“获取有关这个特定电影功能的详细信息”。

//然后你得到详细信息,需要一个可以用来获取一部电影的参数(id)。

getDetails(id){
fetch(id)
displayresults, profit
}

results = this.props.results.map((result, index) => {
          return(
            <li onClick={() => this.getDetails(result.id) ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
              {result.title}{result.id}
              <img  src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
            </li>
          )
        });

答案 1 :(得分:0)

感谢所有的答案,但我实际上已经在朋友的帮助下解决了这个问题。在我的MovieList中,我为每个组件返回了一个名为Movie的新组件,然后我使用MovieList组件中的map函数中的每个电影细节来调用电影细节的API

Movielist

import React, { Component } from 'react';
import Movie from './Movie';

class MoviesList extends Component {
  render() {
    let results;
    if(this.props.results) {
      results = this.props.results.map((result, index) => {
        return(
          <Movie key={result.id} result={result} images={this.props.images}/>
        )
      });
    }

    return (
      <div>
        {results}
      </div>
    )
  }
}

export default MoviesList;

Movie.js

import React, { Component } from 'react';
import MovieDetails from './MovieDetails';

class Movie extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showComponent: false,
      details: []
    }

    this.showDetails = this.showDetails.bind(this);
    this.getDetails = this.getDetails.bind(this);
  }

  componentDidMount() {
    this.getDetails();
  }

  getDetails() {
    let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');

    fetch(request)
      .then((response) => {
        return response.json();
      }).then((data) => {    
        let url = 'https://api.themoviedb.org/3/movie/'+ this.props.result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
        return fetch(url)
      }).then((response) => {
          return response.json();
      }).then((data) => { 
          this.setState({details: data});   
      });
}

  showDetails(id) {
    this.setState({showComponent: true}, () => {
      console.log(this.state.details)
    });
  }

  render() {
    return(
      <li ref={this.props.result.id} id={this.props.result.id} key={this.props.result.id} onClick={this.showDetails}>
        {this.props.result.title}
        <img  src={this.props.images.base_url +`${this.props.images.poster_sizes?this.props.images.poster_sizes[0]: 'err'}` + this.props.result.backdrop_path} alt=''/>
        {this.state.showComponent ? <MovieDetails details={this.state.details}/> : null}
      </li>
    )

  }
}


export default Movie;