API请求返回html标记,React - Redux

时间:2018-05-07 19:45:32

标签: javascript reactjs redux axios

我目前正在使用与redux的反应构建一个简单的Web。 我已成功将redux与app集成,但是我遇到了2个问题我无法解决。 第一个问题是当用户应用过滤器然后触发请求时,组件保持渲染超过限制。

第二个问题是,当用户更改页面时,首先单击请求给出页面标记,但第二次单击时一切正常。

到目前为止,这些是我的代码。

  

处理请求的行动

import { BEGIN_FETCH_MOVIES, FETCHED_MOVIES, FETCH_FAILED_MOVIES } from '../constants';
import axios from 'axios';


//fetch movie
const searchQuery = (url) => {
  return dispatch => {
    //dispatch begin fetching
    dispatch({
      type : BEGIN_FETCH_MOVIES,
    })

    //make a get request to get the movies 
    axios.get(url)
      .then((res) => {
        //dispatch data if fetched 
        dispatch({type : FETCHED_MOVIES, payload : res.data});
      })
      .catch((err) => {
        //dispatch error if error
        dispatch({type : FETCH_FAILED_MOVIES});
    });
  }
  //return the result after the request
}

export default searchQuery;   
  

主要组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { actionSearchMovie, actionSearchSerie } from '../actions'
import DisplayItemMovie from '../components/DisplayItemMovie';
import DisplayItemSerie from '../components/DisplayItemSerie'; 
import DrPagination from "../components/DrPagination";
import { Layout, Divider, Icon, Spin, Row } from 'antd';


//Home component 
class Home extends Component {
  constructor(){
    super();

    this.state = {
      moviePage : 1,
      seriePage : 1,
      urlMovie : '',
      urlSerie : ''
    }
  }

  //make request before the render method is invoked
  componentWillMount(){
    //url
    const discoverUrlMovies = 'https://api.themoviedb.org/3/discover/movie?api_key=72049b7019c79f226fad8eec6e1ee889&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1';

    //requests 
    this.fetchMovie(discoverUrlMovies);
  }

  fetchMovie = ( url ) => {
    this.props.actionSearchMovie(url);
  }



  //handle pagination 

  handleChangePage = (page) =>{
    let url = 'https://api.themoviedb.org/3/discover/movie?api_key=72049b7019c79f226fad8eec6e1ee889&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=' + page;

    this.setState({
      moviePage : page,
      urlMovie : url
    }, ()=> this.state);

    this.fetchMovie(this.state.urlMovie);
  }


  //render
  render() {
    const movies = this.props.movies.results;             //movies
    let displayMovies;           //display movies
    const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;          //spinner

    //if movies and series is undefined, display a spinner
    if(movies.results === undefined){
      displayMovies = <Spin indicator={antIcon} />
    }else {
      //map through movies and series and then display the items 
      displayMovies = movies.results.map((movie) => {
        return <DisplayItemMovie key = {movie.id} movie = {movie} />
      });
    }

    return (
      <div>
        <div className='header'>
          Home
        </div>
        <Divider />
        <Layout style = {{paddingBottom : '1rem', margin : '0 auto' }}>
          <h1 className = 'title'>Movie</h1>
          <Row type = 'flex' style = {{flexWrap : 'wrap'}}>
            {displayMovies}
          </Row>
          <DrPagination total = { movies.total_results } page = { this.handleChangePage } currentPage = { this.state.moviePage }  />          </div>
    )
  }
};

const mapStateToProps = (state) => {
  return{
    movies : state.search_movies,
  }
}

export default connect(mapStateToProps, { actionSearchMovie })(Home);
  

过滤组件

i

mport React, { Component } from 'react';
    import { Row, Col, Select, Button, Divider, InputNumber } from 'antd';

    //official genres by movie db
    const genres = [
      {
          "id": 28,
          "name": "Action"
      },
      {
          "id": 12,
          "name": "Adventure"
      }
  ];

    class Filter extends Component {
      constructor () {
        super();
        this.state = {
          genre : [],
          year : '',
          rate : '',
          filter : false,
        }
      }



      //handle Genre
      handleGenre = (genre) => {
        console.log(genre);
        this.setState({
          genre
        }, () => this.state);
      }

      //handle year
      handleYear = (year) => {
        this.setState({
          year
        }, () => this.state);
      }

      //handle Vote
      handleVote = (rate) =>{
        this.setState({
          rate
        }, ()=> this.state);
      }

      //handle on filter
      handleFilter = () =>{
        const { genre, year, rate } = this.state;
        let url = 'https://api.themoviedb.org/3/discover/movie?api_key=72049b7019c79f226fad8eec6e1ee889&language=en-US&page=1';
        if( genre.length === 0 && rate === "" && year === "" ){
          alert('No filter is selected');
        }else{
          this.setState({
            filter : true
          });
          let genreList = '';
          if(genre.length > 0){
            genreList = '&with_genres='+genre.join();
            url += genreList;  
          }
          if(year !== ""){
            url += '&primary_release_year='+year;
          }
          if(rate !== ""){
            url += '&vote_average='+rate;
          }

          //if filter === true pass the new url to the parent component
          this.props.url(url);
        }
      }

      render() {
        const {filter} = this.state;
        let header;
        const displayGenres = genres.map((genre) => {
          return (
            <Select.Option key = { genre.id }>{genre.name}</Select.Option>
          );
        });

        //
        if(filter === false){
          header = <h1>Top Movies</h1>
        }else{
          header = <h1>Custom Search</h1>
        }
        return (
          <div>
            {header}
            <Divider />
            <Row type = 'flex' align = 'middle' justify = 'center'>
              <Col span = {14}>
                <Row type = 'flex' align = 'middle' justify = 'center'>
                  <Col span = {5}>
                    <Select
                      mode = 'tags'
                      maxTagCount = {1} 
                      style = {{width : '100%'}}
                      allowClear
                      placeholder="All Genre" 
                      onChange = {this.handleGenre}
                    >
                      {displayGenres}
                    </Select>
                  </Col>
                  <Col span = {3}>
                    <Select
                        maxTagCount = {1} 
                        style = {{width : '100%'}}
                        allowClear
                        placeholder="All Rate" 
                        onChange = {this.handleVote}
                    >
                      <Select.Option value = '5'>>5</Select.Option>
                      <Select.Option value = '6'>>6</Select.Option>
                      <Select.Option value = '7'>>7</Select.Option>
                      <Select.Option value = '8'>>8</Select.Option>
                      <Select.Option value = '9'>>9</Select.Option>
                    </Select>
                  </Col>
                  <Col span = {3}>
                    <InputNumber 
                      min = {1980} 
                      max = {2019} 
                      placeholder = 'All Year' 
                      onChange = {this.handleYear}
                    />
                  </Col>
                </Row>
              </Col>

              <Col span = {5}>
                <Button type = 'ghost' onClick = {this.handleFilter}>Filter</Button>
              </Col>
            </Row>
          </div>
        )
      }
    };


    export default Filter;
  

分页组件

import React, { Component } from 'react';
import { Pagination } from 'antd';

export default class DrPagination extends Component {

  //on change page set the new page
  handleChangePage = (page) =>{
    this.props.page(page);
  }


  render() {
    return (
      <div style = {styles.container}>
        <Pagination 
            current = {this.props.currentPage}
            defaultCurrent = {1}
            total = {this.props.total} 
            defaultPageSize = {20}
            onChange = {this.handleChangePage}
            size = 'small'
            showQuickJumper
          />
      </div>
    )
  }
};

const styles = {
  container : {
    width : '100%',
    margin: '1rem',
    display: 'flex',
    justifyContent: 'center',
    alignContent: 'center',
    alignItems: 'center',
  }
}

这是我尝试更改页面时获得的数据(仅在第一次发生时)。 enter image description here

0 个答案:

没有答案