프론트엔드/React 연습과제 해답

리액트 기초이론 8 - 리액트 라우터 해답

syleemomo 2022. 3. 15. 18:46
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