For Programmer
5.LandingPage만들기(3) Load More Button - 영화사이트만들기 본문
React & Node.js 프로젝트/영화사이트 만들기
5.LandingPage만들기(3) Load More Button - 영화사이트만들기
유지광이 2020. 7. 28. 22:47728x90
*loadMoreFunction 만들기(LandingPage.js)
1. button에 onclick 이벤트설정
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button onClick={loadMoreItems}>Load More</button>
</div>
2. state값에 현재페이지값 저장
const [CurrentPage, setCurrentPage] = useState(0);
2.fetch 통신코드가 중복이 되기 때문에 코드낭비를 방지하기위해서 하나의 변수에 저장한다.
const fetchMovies = (endpoint) => {
fetch(endpoint)
.then((response) => response.json()) //응답을 json형태로 변경하여 then의 response에 반환
.then((response) => {
console.log(response);
setMovies([...Movies, ...response.results]); //console로 찍어보면 results배열에 담겨서 데이터보내줌
//스프레드 연산자를 사용하여 배열에 집어넣음
setMainMovieImage(MainMovieImage || response.results[0]);
//로딩될때는 MainMovieImage값이 null이기 때문에 response.results[0]값이 들어오며
//그다음 loding button을 눌릴때마다 MainMovieImage즉 초기이미지로 고정이된다.
//안그러면 로그창에 오류발생
setCurrentPage(response.page);
});
};
*단 마지막에 serCurrentPage(response.page)가 추가 되었는데 그이유는 뒤에나올 loadMoreItems함수에서 fetch통신을 위한 마지막인자 page값을 계속해서 버튼을 눌릴때마다 1씩 올려주어야하기때문이다. (response.page는 1을 반환)
3.loadMoreItems 함수 만들기
const loadMoreItems = () => {
const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=${CurrentPage + 1}`;
fetchMovies(endpoint);
};
Landingpage.js의 전체코드
import React, { useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom';
import { API_URL, API_KEY, IMAGE_BASE_URL } from '../../Config';
import MainImage from './Sections/MainImage';
import GridCards from '../commons/GridCards';
import { Row } from 'antd';
const LandingPage = (props) => {
const [Movies, setMovies] = useState([]); //배열로 값을받기 때문
const [MainMovieImage, setMainMovieImage] = useState(null);
const [CurrentPage, setCurrentPage] = useState(0);
useEffect(() => {
const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=1`;
fetchMovies(endpoint);
}, []);
const fetchMovies = (endpoint) => {
fetch(endpoint)
.then((response) => response.json()) //응답을 json형태로 변경하여 then의 response에 반환
.then((response) => {
console.log(response);
setMovies([...Movies, ...response.results]); //console로 찍어보면 results배열에 담겨서 데이터보내줌
//스프레드 연산자를 사용하여 배열에 집어넣음
setMainMovieImage(MainMovieImage || response.results[0]);
//로딩될때는 MainMovieImage값이 null이기 때문에 response.results[0]값이 들어오며
//그다음 loding button을 눌릴때마다 MainMovieImage즉 초기이미지로 고정이된다.
//안그러면 로그창에 오류발생
setCurrentPage(response.page);
});
};
const loadMoreItems = () => {
const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=${
CurrentPage + 1
}`;
fetchMovies(endpoint);
};
return (
<div style={{ width: '100%', margin: '0' }}>
{/*Main Image */}
{MainMovieImage && ( //만약 이러한 작업을 하지않을 경우 React는 MainMovieImage를 state에 넣기전에
//페이지를 렌더링 할려고 하여 backrop_path가 null 에러가 발생한다.
/*console.log 보면 backdrop_path에 이미지에대한 이름이 담겨있다.*/
<MainImage
image={`${IMAGE_BASE_URL}w1280/${MainMovieImage.backdrop_path}`} //영화이미지
title={MainMovieImage.original_title} //영화제목
text={MainMovieImage.overview} //영화에대한설명
/>
)}
<div style={{ width: '85%', margin: '1rem auto' }}>
<h2>Movies by latest</h2>
<hr />
{/*Movie Grid Cards */}
<Row gutter={[16, 16]}>
{/*gutter는 Col간의 위 아래여백을 줄때 사용 */}
{Movies &&
Movies.map((movie, index) => (
<React.Fragment key={index}>
<GridCards
image={
movie.poster_path
? `${IMAGE_BASE_URL}w500/${movie.poster_path}`
: null
}
movieName={movie.original_title}
movieId={movie.id}
/>
</React.Fragment>
))}
</Row>
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button onClick={loadMoreItems}>Load More</button>
</div>
</div>
);
};
export default withRouter(LandingPage);
*번외로 페이스북이나 인스타그램처럼 밑으로 계속해서 스크롤을 내릴경우 자동으로 데이터를 불러오는 코드를 만들고 싶다면 다음코드를 이용하면된다.(LandingPage.js)
import React, { useEffect, useState, useRef } from 'react';
import { Typography, Row, Button } from 'antd';
import { API_URL, API_KEY, IMAGE_BASE_URL } from '../../Config';
import MainImage from './Sections/MainImage';
import GridCard from '../commons/GridCards';
const { Title } = Typography;
function LandingPage() {
const buttonRef = useRef(null);
const [Movies, setMovies] = useState([]);
const [MainMovieImage, setMainMovieImage] = useState(null);
const [Loading, setLoading] = useState(true);
const [CurrentPage, setCurrentPage] = useState(0);
useEffect(() => {
const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=1`;
fetchMovies(endpoint);
}, []);
useEffect(() => {
window.addEventListener('scroll', handleScroll);
}, []);
const fetchMovies = (endpoint) => {
fetch(endpoint)
.then((result) => result.json())
.then((result) => {
setMovies([...Movies, ...result.results]);
setMainMovieImage(MainMovieImage || result.results[0]);
setCurrentPage(result.page);
}, setLoading(false))
.catch((error) => console.error('Error:', error));
};
const loadMoreItems = () => {
let endpoint = '';
setLoading(true);
console.log('CurrentPage', CurrentPage);
endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=${
CurrentPage + 1
}`;
fetchMovies(endpoint);
};
const handleScroll = () => {
const windowHeight =
'innerHeight' in window
? window.innerHeight
: document.documentElement.offsetHeight;
const body = document.body;
const html = document.documentElement;
const docHeight = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight
);
const windowBottom = windowHeight + window.pageYOffset;
if (windowBottom >= docHeight - 1) {
console.log('clicked');
buttonRef.current.click();
}
};
return (
<div style={{ width: '100%', margin: '0' }}>
{MainMovieImage && (
<MainImage
image={`${IMAGE_BASE_URL}w1280/${MainMovieImage.backdrop_path}`}
title={MainMovieImage.original_title}
text={MainMovieImage.overview}
/>
)}
<div style={{ width: '85%', margin: '1rem auto' }}>
<Title level={2}> Movies by latest </Title>
<hr />
<Row gutter={[16, 16]}>
{Movies &&
Movies.map((movie, index) => (
<React.Fragment key={index}>
<GridCard
image={
movie.poster_path
? `${IMAGE_BASE_URL}w500/${movie.poster_path}`
: null
}
movieId={movie.id}
movieName={movie.original_title}
/>
</React.Fragment>
))}
</Row>
{Loading && <div>Loading...</div>}
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button ref={buttonRef} className="loadMore" onClick={loadMoreItems}>
Load More
</button>
</div>
</div>
</div>
);
}
export default LandingPage;
* 위의 길이를 구할때 쓰는 ScrollHeight,offsetHeight,clientHeight 등에대한 설명이 자세하게 나와있다.
https://sometimes-n.tistory.com/22
* innerHeight,outerHeight 등에 대한 내용이 자세하게 나와있다.
실행결과
동영상강의
728x90
'React & Node.js 프로젝트 > 영화사이트 만들기' 카테고리의 다른 글
7. 영화 출연진들 가져오기 - 영화사이트 만들기 (0) | 2020.07.29 |
---|---|
6.Movie Detail 페이지 만들기 - 영화사이트 만들기 (0) | 2020.07.29 |
4.Landing Page 만들기(2) GridCard Componenet- 영화사이트 만들기 (0) | 2020.07.28 |
3. Landing Page 만들기(1) - 영화사이트 만들기 (0) | 2020.07.28 |
2.The MovieDB API 설정 - 영화사이트 만들기 (0) | 2020.07.28 |
Comments