【问题标题】:React setState fetch API反应 setState 获取 API
【发布时间】:2018-06-10 04:28:02
【问题描述】:

我现在开始学习 React 并创建我的第二个项目。我正在尝试使用 MovieDb API 创建电影搜索应用程序。当我得到最初的电影列表时,一切都很好。但是onClick每个列表项我想显示每部电影的详细信息。我使用 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;

【问题讨论】:

  • 我还忘了补充一点,每次搜索的 state.details 总是相同的。每个其他状态都会随着新的搜索而改变,但 state.details 始终保持不变
  • 请注意,我建议您不要在帖子中包含您的 api 密钥...
  • 你能澄清一下实际的问题是什么吗?是什么导致了这个问题?特别是哪个api调用?此外,您应该查看axios 以在客户端进行 API 调用。
  • 完全忘记了钥匙...谢谢指出
  • 我在考虑 AXIOS,因为我只使用过 Jquery 或 Vanilla JS 进行 API 调用,但决定尝试 fetch API,这似乎与 AXIOS 非常相似

标签: reactjs fetch-api setstate


【解决方案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>
          )
        });

【讨论】:

    【解决方案2】:

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

    电影家

    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;
    

    电影.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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 2018-12-14
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      相关资源
      最近更新 更多