GraphQL 및 React를 사용하여 영화 사이트 만들기 - 두 번째 섹션
계속하기 전에 저는 멋있다고 생각했기 때문에 HTTP 클라이언트, 예를 들어axios를 사용하여 GraphQL 서버에 요청할 수 있습니다!이것 좀 봐:
const query = `{
newMovies {
id
title
}
}`
const url = 'http://localhost:4000/graphql?query='+query;
axios.get(url)
.then(res => console.log(res.data.data.newMovies))
관심 있으시면 graphQL 인터페이스를 사용할 때 url의 변화에 주의하여 설정의 실제 상황을 보실 수 있습니다. - 연구를 진행했습니다.그러나 생산을 더욱 쉽고 즐겁게 하기 위해 우리는 GraphQL 클라이언트를 사용하여 HTTP 클라이언트를 대체할 수 있다.
선택할 수 있는 고객은 매우 적다.이 강좌에서 나는 Apollo Client을 사용할 것이다.Apollo도graphQL 서버를 제공했지만
express-graphql
으로 만들었기 때문에 Apollo의 이 부분을 사용하지 않고 Apollo 클라이언트입니다. 말 그대로react에서graphQL을 작성할 수 있습니다.너트 케이스에서
계속하려면 github 복제 저장소에서 지점 이름
Graphql-api
을 서명해야 합니다. 왜냐하면react단을 주목하기 때문에 모든 코드는 client
디렉터리, 즉react 응용 프로그램 코드에 기록됩니다.분명히 이것은 초보자의 강좌가 아니다.만약 네가 반응을 모르지만, 내가 쓴 기초 지식을 배우는 것에 흥미가 있다.
먼저 다음 패키지를 설치합니다.
npm install apollo-boost react-apollo graphql-tag graphql --save
게임 계획은 ApolloProvider
으로 우리의react 응용 프로그램을 포장하고 GraphQL 클라이언트를react 도구에 추가하는 것입니다.그리고 graphql-tag
을 통해 graphQL 조회를 진행합니다.현재
./client/index.js
에서 이 설정을 볼 수 있습니다import React from 'react';
import ReactDOM from 'react-dom';
import './style/style.scss';
const App = () => {
return <div>Hello World2</div>
}
ReactDOM.render(
<App />,
document.querySelector('#root')
);
첫 번째 단계는 전체 응용 프로그램을 ApolloProvider
으로 포장하는 것이다.공급자는 반응하기 위해 GraphQL 클라이언트가 필요합니다.import { ApolloProvider, graphql } from 'react-apollo';
...
const client = new ApolloClient({
uri: "http://localhost:4000/graphql"
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider> ,
document.querySelector('#root')
);
GraphQL 서버가 ApolloClient
을 가리키지 않으면 uri
에 /graphql
이 필요합니다.그래서 우리의 예에서 그것을 없애고 new ApolloClient()
만 사용하면 된다이제 클라이언트에 액세스하여 다음과 같이 질의할 수 있습니다.
import { ApolloProvider, graphql } from 'react-apollo';
import gql from 'graphql-tag';
import ApolloClient from 'apollo-boost';
const AppComponent = (props) => {
if(props.data.loading) return '<div>loading</div>';
return <div>{props.data.newMovies[0].title}</div>
}
const query = gql`{ newMovies { title } }`;
const App = graphql(query)(AppComponent)
우리는 AppComponent
으로 graphql
을 포장하고 검색을 도구에 주입한 후에 props.data.newMovies
을 우리에게 영화 결과를 주었다.시작합시다.
우리가 구축하고 있는 응용 프로그램은 위에 표시된 하나의 제목보다 예시가 더 크기 때문에 분리합니다.
./client/index.js
부터.import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import { HashRouter, Switch, Route } from 'react-router-dom'
import NewMovies from './components/NewMovies';
import './style/style.scss';
const client = new ApolloClient();
const Root = () => {
return (
<HashRouter >
<ApolloProvider client={client}>
<Switch >
<Route exact path="/" component={NewMovies} />
</Switch>
</ApolloProvider>
</HashRouter>
)
}
ReactDOM.render(
<Root />,
document.querySelector('#root')
);
간단하다가져온 구성 요소(NewMovies
)는 존재하지 않지만, 이것이 ./client/index.js
에 필요한 모든 코드입니다.마찬가지로 우리가 사용할 모든 구성 요소는
Switch
구성 요소에 지정됩니다.따라서 전체 응용 프로그램은 ApolloProvider
으로 포장되어nutshell 부분과 완전히 같다.최고의 영화 얻기
./client/components/NewMovies.js
에 파일을 만들고 필요한 패키지를 가져오는 것부터 시작합시다import React, { Component} from 'react'
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
다음은 newMovies
GraphQL 검색 결과를 NewMovies
구성 요소에 주입합니다class NewMovies extends Component {
...
}
const query = gql`
{
newMovies {
id
poster_path
title
}
}
`
export default graphql(query)(NewMovies);
이 설정을 통해 하나의 대상 수조에 NewMovies
구성 요소 도구가 주입되고 this.props.data.newMovies
에 접근할 수 있습니다.이를 활용하자:class NewMovies extends Component {
Movies(){
return this.props.data.newMovies.map(movie => {
return (
<article key={movie.id} className="movie_list">
<img src={movie.poster_path} />
<h1>{movie.title}</h1>
</article>
);
})
}
render() {
if(this.props.data.loading) return <div>loading</div>
return this.Movies()
}
}
찾았습니다.주의해야 할 것은newMovies
결과를 얻기 전에 반응 구성 요소를 불러옵니다.loading
속성을 제공했다. 이 속성은 데이터를 얻을 때 true
으로 설정하고 데이터가 준비되어 사용할 때 false
우리가 다른 구성 요소를 계속 토론하기 전에, 포스터를 선택할 때 더 많은 정보를 얻을 수 있도록 닻으로 영화 포스터를 포장합시다.
이를 위해
Link
패키지의 react-router-dom
구성 요소를 사용합니다.import { Link } from 'react-router-dom'
class NewMovies extends Component {
Movies(){
return this.props.data.newMovies.map(movie => {
return (
<article key={movie.id} className="movie_list">
<Link to={"/info/"+movie.id}>
<img src={movie.poster_path} />
</Link>
...
예를 들어 포스터를 클릭할 때마다 /info/1
으로 안내됩니다.이 루트를 포착하는 공유기를 추가하려면
./client/index.js
으로 돌아가야 합니다....
import MovieInfo from './components/MovieInfo';
...
const Root = () => {
return (
<HashRouter >
<ApolloProvider client={client}>
<Switch >
<Route exact path="/" component={TopMovies} />
<Route exact path="/info/:id" component={MovieInfo} />
</Switch>
...
물론,react 루트 () 의 기능입니다.Movie Info 구성 요소를 살펴보도록 하겠습니다.
먼저
./client/components/MovieInfo.js
에 파일을 만들고 다음을 추가합니다.import React, { Component } from 'react'
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
class MovieInfo extends Component {
render(){
if(this.props.data.loading) return <div>loading</div>
return (
<div>{this.props.data.movieInfo.title}</div>
)
}
}
const query = gql`
{movieInfo(id: "284054") {
title
}}`;
export default graphql(query)(MovieInfo);
그것은 정상적으로 일할 수 있습니까?우리는 하드코딩된
id
을 조회하고 있습니다. 이것은 우리가 원하는 것이 아니라, 반대로, 우리의react 구성 요소 도구에서graphql 조회에 ID를 전달하고자 합니다.react-apollo
은 우리에게 Query
구성 요소를 제공하여 우리가 이 점을 할 수 있도록 한다.import { Query, graphql } from 'react-apollo'
class MovieInfo extends Component {
render(){
const id = this.props.match.params.id;
return (
<Query query={query} variables={{id}} >
{
(({loading, err, data}) => {
if(loading) return <div>loading</div>
return (
<div>{data.movieInfo.title}</div>
)
})
}
</Query>
)
}
}
const query = gql`
query MovieInfo($id: String) {
movieInfo(id: $id) {
title
}
}
`;
거의 똑같지만 Query
이 있으면 우리는 변수를 전달할 수 있다.이제 구성 요소의 나머지 부분을 개발합시다.
Query
내에 다음 코드를 반환합니다return(
<div>
<header style={{backgroundImage: 'url("https://image.tmdb.org/t/p/w500///'+data.movieInfo.poster_path+'")'}}>
<h2 className="title">{data.movieInfo.title}</h2>
</header>
<article className="wrapper">
<p className="description">{data.movieInfo.overview}</p>
<div className="sidebar">
<img src={"https://image.tmdb.org/t/p/w500///"+data.movieInfo.poster_path} className="cover_image" alt="" />
<ul>
<li><strong>Genre:</strong> {data.movieInfo.genres}</li>
<li><strong>Released:</strong>{data.movieInfo.release_date}</li>
<li><strong>Rated:</strong> {data.movieInfo.vote_average}</li>
<li><strong>Runtime:</strong> {data.movieInfo.runtime}</li>
<li><strong>Production Companies:</strong> {data.movieInfo.production_companies}</li>
</ul>
<div className="videos">
<h3>Videos</h3>
{/* videos */}
</div>
{/* reviews */}
</div>
{/* credits */}
</article>
</div>
)
보시다시피 요청하지 않은 검색 속성에 접근하려고 시도하고 있습니다.이 명령을 실행하면 요청이 실패하면 404 오류가 발생합니다.따라서 title
보다 더 많은 속성을 요청하기 위해 조회를 업데이트해야 합니다.query MovieInfo($id: String) {
movieInfo(id: $id) {
title
overview
poster_path
genres
release_date
vote_average
runtime
production_companies
}
}
`;
이 업데이트와git 저장소에서 제공할 css가 있습니다. 우리가 계속 하고 있는 부분은 다음과 같습니다.
코드 주석에서 보듯이 우리는 페이지에 동영상, 평론, 신용을 추가해야 한다.
비디오 추가
에서 GraphQL 쿼리를 설계하여
movieInfo
쿼리에서 비디오를 얻을 수 있도록 합니다.먼저 이렇게 합시다.const query = gql`
query MovieInfo($id: String) {
movieInfo(id: $id) {
...
videos {
id
key
}
}
}
`;
이 영상들은 때때로 한 개에 그치지 않기 때문에 진열 형식으로 나타난다.따라서 이 수조를 처리하는 가장 좋은 방법은 MovieInfo
구성 요소 안에 모든 영상을 되돌려주는 단독 방법을 만드는 것이다.class MovieInfo extends Component {
renderVideos(videos){
return videos.map(video => {
return (
<img key={video.id}
onClick={()=> this.videoDisplay(video.key)}
className="video_thumbs"
src={`http://img.youtube.com/vi/${video.key}/0.jpg`}
/>
)
})
}
render(){
...
{/* videos */}
{this.renderVideos(data.movieInfo.videos)}
...
첫 번째 강좌에서 설명한 바와 같이 key
대상의 videos
은 유튜브 영상 ID를 가리킨다. 유튜브는 이 특정 형식의 캡처 이미지를 사용할 수 있게 한다(src
속성에서 전달).또한 앞에서 언급한 바와 같이 우리가 ID를 사용하는 이유는 바로 key
의 독특한 기능-React가 필요하다는 것을 알고 있기 때문이다.사용자가 이 축소판을 눌렀을 때, 나는 화면에 유튜브 영상인
onClick={()=> this.videoDisplay(video.key)}
을 불러오고 싶었다.이 기능을 만듭니다.우리가 이 점을 실현하는 방법은 상태를 바꾸는 것이다
class MovieInfo extends Component {
constructor(){
super();
this.state={
video: null
}
}
videoDisplay(video){
this.setState({
video
})
}
videoExit(){
this.setState({
video: null
})
}
...
페이지가 video
을 불러올 때 상태가 null
이고 미리 보기 그림을 누르고 videoDisplay
을 터치하면 video
상태가 유튜브 영상 key
을 값으로 합니다.videoExit
메서드를 터치하면 video
상태가 null
으로 리셋됨을 볼 수 있습니다마지막으로 상태가 바뀔 때 동영상을 표시하는 방법이 필요하기 때문에 다른 방법을 만듭니다.위 방법 아래에서 이 방법을 추가합니다.
videoToggle(){
if(this.state.video) return(
<div className="youtube-video">
<p onClick={() => this.videoExit()}>close</p>
<iframe width="560" height="315" src={`//www.youtube.com/embed/${this.state.video}` } frameborder="0" allowfullscreen />
</div>
)
}
그리고 간단하게 페이지의 모든 위치에 보여줍니다<div className="videos">
{this.videoToggle()}
<h3>Videos</h3>
{this.renderVideos(data.movieInfo.videos)}
</div>
마찬가지로 video
상태가 null
이면 {this.videoToggle()}
은 아무런 조작도 하지 않습니다.상태가 비어 있지 않으면 - video
에 키가 있으면 {this.videoToggle()}
으로 비디오를 렌더링합니다.영화 학점과 평론을 추가하다
나는 영화 평론과 영화 학점을 각자의 독립된 부분에 두기로 결정했다.빈 구성 요소 파일을 만들고
MovieInfo
구성 요소에서 가져오고 사용하며 조회를 업데이트합니다../client/components/MovieInfo.js
에 변경 내용 추가import MovieReviews from './MovieReviews'
import MovieCredits from './MovieCredits'
class MovieInfo extends Component {
...
{/* reviews */}
<MovieReviews reviews={data.movieInfo.movieReviews} />
</div>
{/* credits */}
<MovieCredits credits={data.movieInfo.movieCredits} />
</article>
}
...
const query = gql`
query MovieInfo($id: String) {
movieInfo(id: $id) {
...
movieReviews {
id
content
author
}
movieCredits{
id
character
name
profile_path
order
}
}
}
`;
...
우리는 movieReviews
과 movieCredits
조회에서 데이터를 얻어 각각의 구성 요소에 전달합니다.지금 저희는 그냥 데이터를 빨리 보여주는 거예요.영화 학점 구성 요소
다음 코드를
./client/components/MovieCredits.js
에 추가import React, { Component } from 'react'
export class MovieCredits extends Component {
renderCast(credits){
return credits.map(cast => {
return (
<li key={cast.id}>
<img src={`https://image.tmdb.org/t/p/w500//${cast.profile_path}`} />
<div className="castWrapper">
<div className="castWrapperInfo">
<span>{cast.name}</span>
<span>{cast.character}</span>
</div>
</div>
</li>
)
})
}
render() {
return (<ul className="cast">{this.renderCast(this.props.credits)}</ul>)
}
}
export default MovieCredits
위에서 아무런 새로운 해석도 없다영화 평론 구성 요소
다음 코드를
./client/components/MovieReviews.js
에 추가import React, { Component } from 'react'
class MovieReviews extends Component {
renderReviews(reviews){
return reviews.map(review => {
return (
<article key={review.id}><h4>{review.author} writes</h4>
<div>{review.content}</div>
</article>
)
})
}
render() {
return(
<div className="reviews">
{this.renderReviews(this.props.reviews)}
</div>
)
}
}
export default MovieReviews;
이렇게이것이 바로 학점, 동영상, 평론의 표시 방식이다.
결론
전체 응용 프로그램 (예를 들어 it 브래킷) 은 같은 저장소에서 찾을 수 있으며, demo here을 볼 수 있습니다.그것은 세 개의 분기 react-app branch과 master branch에 완전한 코드를 가지고 있으며, 모든 강좌 건축은 서로의 꼭대기에 있다.그 중에서 Graphql-api branch의 코드는
Reference
이 문제에 관하여(GraphQL 및 React를 사용하여 영화 사이트 만들기 - 두 번째 섹션), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aurelkurtula/creating-a-movie-website-with-graphql-and-react---part-two-3ahf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)