들어가기
Client로 접속했을때,
모든 식당들이 나열되어 보이는 page
import { gql, useQuery } from '@apollo/client'
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import { Link } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'
import Restaurant from '../../components/restaurant'
import { CATEGORY_FRAGMENT, RESTAURANT_FRAGMENT } from '../../fragments'
import {
RestaurantsPageQuery,
RestaurantsPageQueryVariables,
} from '../../graphql/__generated__'
const RESTAURANTS_QUERY = gql`
query restaurantsPage($input: RestaurantsInput!) {
allCategories {
ok
error
categories {
...CategoryParts
}
}
///restaurantsPage를 실행시키면,
///server의 allCategories와 restaurants query가 실행됨.
///restaurants의 input(RestaurantInput)부분은
///page를 입력받는 부분임.
///...CategoryParts와 ...RestaurantParts 부분은
///frahment로 만들어 놓은 부분.
///다음 post에서 다룰 예정.
restaurants(input: $input) {
ok
error
totalPages
totalResults
results {
...RestaurantParts
}
}
}
${RESTAURANT_FRAGMENT}
${CATEGORY_FRAGMENT}
`
interface IFromProps {
search: string
}
///restaurant search하기 위해서 만들어 놓은 props
const Restaurants = () => {
const [page, setPage] = useState(1)
///page의 default값은 1로~
const { data, loading } = useQuery<
RestaurantsPageQuery,
RestaurantsPageQueryVariables
>(RESTAURANTS_QUERY, {
variables: { input: { page } },
})
///위에서 만든 restaurantsPage Query임.
///variables는 page를 input함.
const onNextPageClick = () => setPage((current) => current + 1)
const onPrevPageClick = () => setPage((current) => current - 1)
///page를 넘기는 화살표를 클릭했을시 실행 될 함수.
const { register, handleSubmit, getValues } = useForm()
///useForm
const navigate = useNavigate()
///useNavigate설정.
const onSearchSubmit = () => {
console.log(getValues())
const search = getValues().search
navigate({
pathname: '/search',
search: `?term=${search}`,
})
}
///serch칸에서 keyword를 입력후 enter했을때,
///실행될 함수.
///밑의 form(search)에서 state를 받아서
/// http://localhost:3000/search?term=ccc
///의 주소로 이동시켜줌.
///term이 keyword임.
return (
<div>
<form
onSubmit={handleSubmit(onSearchSubmit)}
className="bg-gray-800 w-full py-40 flex items-center justify-center"
>
///search Restaurant react-hook-form
<input
{...register('search', { required: true, min: 3 })}
type="search"
className="input rounded-md border-0 w-3/4 md:w-7/12"
placeholder="Search Restaurant"
/>
</form>
///Search restaurant react-hook-form
{!loading && (
<div className="px-5 mt-8 pb-20 max-w-screen-2xl mx-auto">
<div className="flex justify-around max-w-sm mx-auto">
///allCategories로 불러들이 data 나열함
{data?.allCategories.categories?.map((category) => (
<Link key={category.id} to={`category/${category.slug}`}>
///category 이미지 클릭시 그 category 페이지로 이동.
<div>
<div
className="w-16 h-16 bg-cover group-hover:bg-gray-200 rounded-full"
style={{ backgroundImage: `url(${category.coverImg})` }}
></div>
<span className="mt-1 text-sm text-center font-bold">
{category.name}
</span>
</div>
</Link>
))}
</div>
<div className="mt-16 grid md:grid-cols-3 gap-x-5 gap-y-10">
///restaurants를 화면에 뿌려줌.
{data?.restaurants.results?.map((restaurant) => (
///<Restaurant> component를 만들어 놓앗음.
<Restaurant
key={restaurant.id}
id={restaurant.id + ''}
coverImg={restaurant.coverImg}
name={restaurant.name}
categoryName={restaurant.category?.name}
/>
))}
</div>
<div className="grid grid-col-3 text-center max-w-md items-center mx-auto mt-10">
///Pagination을 설정함.
{page > 1 ? (
<button
onClick={onPrevPageClick}
className="focus:outline-none font-medium text-2xl"
>
←
</button>
) : (
<div></div>
)}
<span>
Page {page} of {data?.restaurants.totalPages}
</span>
{page !== data?.restaurants.totalPages ? (
<button
onClick={onNextPageClick}
className="focus:outline-none font-medium text-2xl"
>
→
</button>
) : (
<div></div>
)}
</div>
</div>
)}
</div>
)
}
export default Restaurants
하나의 Query에 server의 두개의 query(allCategories, restaurants)를 호출한다는 점을 유심히 알아둔다.
하나의 restaurant component는 너무많이 사용되어서
component로 만듬
import React from 'react'
import { Link } from 'react-router-dom'
interface IRestaurantProps {
id: string
coverImg: string
name: string
categoryName?: string
}
///id, coverImg, name, categoryName을 받음.
const Restaurant: React.FC<IRestaurantProps> = ({
///component의 type은 React.Fc임.
id,
coverImg,
name,
categoryName,
}) => {
return (
<Link to={`/restaurants/${id}`}>
///클릭하면, restaurant detail page로 이동함.
<div className="flex flex-col">
<div
style={{ backgroundImage: `url(${coverImg})` }}
className="py-28 bg-center bg-cover mb-2"
></div>
<h3 className="text-xl font-medium">{name}</h3>
<span>{categoryName}</span>
</div>
</Link>
)
}
export default Restaurant
NOTICE!!
client user가 접속했을때, 맨 처음에 나오는 page.
front에서 하나의 query(restaurantsPage)로 server의 두개의
query(allCategories, restaurants)를 실행시켜서 두개의 data를 불러옴,