3

This is the react code for a sample homepage. I wanted to make it such that when the buttons are clicked it will run the function and then update the page. But instead it keeps giving the alerts. I've confirmed that the fetch is indeed pulling data from the API but the onClick is the one that isn't working.

import React, { Component } from 'react';
import Grid from '@material-ui/core/Grid';
import Container from '@material-ui/core/Container';
import Movie from './movieoutline/samplemovie';
import './Home.css';
import { Button, ButtonToolbar } from 'react-bootstrap';
import * as FaIcons from 'react-icons/fa';


export class Home extends Component {

    constructor(props) {
        super(props);
        this.state = { movies: [], page:1, maxpage:0 }
    }

    refreshlist() {
        let _page = this.state.page;
        const sort = "popularity.desc";
        const apikey = process.env.REACT_APP_TMDB_APP_KEY;
        const url = "https://api.themoviedb.org/3/discover/movie?api_key=" + apikey + "&language=en-US&sort_by=" + sort + "&include_adult=false&include_video=false&page="+_page+"&with_watch_monetization_types=flatrate";
        fetch(url)
            .then(response => response.json())
            .then(data => {
                this.setState({ movies: data.results, page:data.page, maxpage:data.total_pages});
                console.log(this.state);
            })
    }

    componentDidMount() {
        this.refreshlist();
    }

    componentDidUpdate() {
        this.refreshlist();
    }

    fowardbtn(){
        if(this.state.page == this.state.maxpage ){
            return true;
        } else{
            return false;
        }
    }

    backwardbtn(){
        if(this.state.page == 1 ){
            return true;
        } else{
            return false;
        }
    }

    render() {
        const { movies } = this.state;
        return (
            <Container maxWidth="xl" id="testApp">
                <div className="foward">
                    <Button className='fowardbtn' variant='primary' onClick = {
                        this.fowardbtn() 
                        ? 
                        alert("This is the last page")
                        :
                        this.setState({page: this.state.page+1}), this.refreshlist()
                        }>
                        <FaIcons.FaChevronCircleRight className='movie-icons' />
                    </Button>
                </div>
                <div className="backward">
                    <Button className='backwardbtn' variant='primary' onClick = {
                        this.backwardbtn() 
                        ? 
                        alert("This is the first page")
                        :
                        this.setState({page: this.state.page-1}), this.refreshlist()
                        }>
                        <FaIcons.FaChevronCircleLeft className='movie-icons' />
                    </Button>
                </div>
                <div className='item container-fluid d-flex justify-content-center'>
                    <Grid container spacing={2} direction="row" justifyContent="center" alignItems="center">
                        {movies.map(movie =>
                            <Grid item lg={2} md={3} sm={4} xs={5}>
                                < Movie movie={movie} />
                            </Grid>
                        )}
                    </Grid>
                </div>
            </Container>
        );
    }
}

Edit:

When I remove the alert code it gives an Unhandled Rejection error, saying that a component called the setState method too often.

2 Answers 2

1

Please try this.

import React, { Component } from 'react';
import Grid from '@material-ui/core/Grid';
import Container from '@material-ui/core/Container';
import Movie from './movieoutline/samplemovie';
import './Home.css';
import { Button, ButtonToolbar } from 'react-bootstrap';
import * as FaIcons from 'react-icons/fa';


export class Home extends Component {

    constructor(props) {
        super(props);
        this.state = { movies: [], page:1, maxpage:0 }
    }

    refreshlist() {
        let _page = this.state.page;
        const sort = "popularity.desc";
        const apikey = process.env.REACT_APP_TMDB_APP_KEY;
        const url = "https://api.themoviedb.org/3/discover/movie?api_key=" + apikey + "&language=en-US&sort_by=" + sort + "&include_adult=false&include_video=false&page="+_page+"&with_watch_monetization_types=flatrate";
        fetch(url)
            .then(response => response.json())
            .then(data => {
                this.setState({ movies: data.results, page:data.page, maxpage:data.total_pages});
                console.log(this.state);
            })
    }

    componentDidMount() {
        this.refreshlist();
    }

    componentDidUpdate() {
        this.refreshlist();
    }

    fowardbtn(){
        if(this.state.page == this.state.maxpage ){
            return true;
        } else{
            return false;
        }
    }

    backwardbtn(){
        if(this.state.page == 1 ){
            return true;
        } else{
            return false;
        }
    }

    render() {
        const { movies } = this.state;
        return (
            <Container maxWidth="xl" id="testApp">
                <div className="foward">
                    <Button className='fowardbtn' variant='primary' onClick = {
                        this.fowardbtn() 
                        ? 
                        () => alert("This is the last page")
                        :
                        () => {
                            this.setState({page: this.state.page+1}); 
                             this.refreshlist();
                             }
                        }>
                        <FaIcons.FaChevronCircleRight className='movie-icons' />
                    </Button>
                </div>
                <div className="backward">
                    <Button className='backwardbtn' variant='primary' onClick = {
                        this.backwardbtn() 
                        ? 
                        () => alert("This is the last page")
                        :
                        () => {
                            this.setState({page: this.state.page-1}); 
                             this.refreshlist();
                             }
                        }>
                        <FaIcons.FaChevronCircleLeft className='movie-icons' />
                    </Button>
                </div>
                <div className='item container-fluid d-flex justify-content-center'>
                    <Grid container spacing={2} direction="row" justifyContent="center" alignItems="center">
                        {movies.map(movie =>
                            <Grid item lg={2} md={3} sm={4} xs={5}>
                                < Movie movie={movie} />
                            </Grid>
                        )}
                    </Grid>
                </div>
            </Container>
        );
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

okay. for example, in onClick={ *method* } , { , } means React Code in HTML. so If you use like this onClick={ *method* }, method is excuted by render without click event. So if method is alert('...') then alert will display when once page is loaded. so if you use click event is correctly, you have to use arrow function like this. onClick={() => method}. In this case, when once page is loaded, first it will excute arrow function, then if by click event it will excute method.
Likewise, if you use onClick={ this.setState(...) }, it will exucte this.setState() when once page render, then by the setState() method, will page is rerender, then will excute this.setState() by rendering... therefore the page goes into an infinite loop.
1

Replace your button with below and check

<Button className='backwardbtn' variant='primary' 
     onClick = {() => {
       this.backwardbtn() ? 
       alert("This is the first page") :
       this.setState({page: this.state.page-1});
       this.refreshlist();
     }}>
  <FaIcons.FaChevronCircleLeft className='movie-icons' />
</Button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.