728x90
import React from 'react'
import { useParams, NavLink, useSearchParams, useLocation } from "react-router-dom";
// import posts from '../postData'
import './Post.css'
function Post({ movies }){
const params = useParams();
let [searchParams, setSearchParams] = useSearchParams()
const applyActiveColor = ({ isActive }) => (isActive ? {color: 'orangered'} : {})
const changeQueryString = (e) => {
const filter = e.target.value
if(filter){
setSearchParams({ filter })
}else{
setSearchParams({})
}
}
const QueryNavLink = ({ to, children, ...props }) => {
const location = useLocation();
console.log(location)
return <NavLink to={to + location.search} {...props}>{children}</NavLink>
}
// 필터링된 목록으로 렌더링하기
const moviesFiltered = movies
.filter( movie => {
const filter = searchParams.get('filter')
if(!filter) return true;
const title = movie.title.toLowerCase()
return title.includes(filter.toLowerCase())
})
const movie = moviesFiltered[params.movieId]
return (
<>
{/* 쿼리스트링을 이용한 검색 */}
<br/><input className="filter-post" value={searchParams.get('filter') || ""} onChange={changeQueryString} placeholder="Search post ..."/>
{/* 특정 블로그 포스트 */}
{movie ?
<div className="post-container">
<h1>{movie.title}</h1>
<img src={movie.medium_cover_image} alt={movie.title}/>
<p>{movie.summary}</p>
<h3>{movie.genres.join(" ")}</h3>
</div> :
<h1>MOVIE PAGE</h1>}
{/* 블로그 포스트 전체목록 */}
{moviesFiltered
.map( (movie, id) => {
return (
<QueryNavLink key={id} to={`/movies/${id}`} className="post-item" style={applyActiveColor}>{movie.title}</QueryNavLink>
)
})}
</>
)
}
export default Post
import './App.css';
import React, { Component } from 'react';
import { Route, Routes } from 'react-router-dom';
import { Home, About, NotFound, Post } from './pages';
import Menu from './Menu'
import Sidebar from './Sidebar'
import Button from './Button'
class App extends Component {
homeMenu = [
{
url: "/",
name: "HOME"
},
{
url: "/about",
name: "ABOUT"
},
{
url: "/movies",
name: "MOVIE"
},
]
state = {
open: false,
movies: []
}
showSidebar = () => {
this.setState({ open: !this.state.open })
}
componentDidMount(){
fetch('https://yts.mx/api/v2/list_movies.json?limit=12')
.then( res => res.json())
.then( result => {
const {data: {movies}} = result
console.log(movies)
this.setState({movies})
})
}
render(){
const { open, movies } = this.state
const { homeMenu } = this
return (
<div className="App">
<Button handleClick={this.showSidebar}>Menu</Button>
<Sidebar open={open}>
<Menu menus={homeMenu}></Menu>
</Sidebar>
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/about" element={<About/>}/>
<Route path="/movies" element={<Post movies={movies}/>}>
<Route path=":movieId" element={<Post movies={movies}/>} />
</Route>
<Route path="*" element={<NotFound/>}/>
</Routes>
</div>
);
}
}
export default App;
728x90
'프론트엔드 > React 연습과제 해답' 카테고리의 다른 글
리액트 기초이론 9 - 리액트 훅(React Hook) 해답 (0) | 2022.03.15 |
---|---|
리액트 기초이론 7 - 이벤트(Event) 처리하기 해답 (0) | 2022.03.09 |
리액트 기초이론 5 - 컴포넌트 스타일링 3 - Styled Components 해답 (0) | 2022.03.07 |
리액트 기초이론 5 - 컴포넌트 스타일링 2 - SASS 해답 (0) | 2022.03.02 |
리액트 기초이론 5 - 컴포넌트 스타일링 해답 (0) | 2022.02.28 |