230616 - React(router-youtube)

๋ฐฑ์Šน์—ฐยท2023๋…„ 6์›” 16์ผ
1

๐Ÿšฉ React

router์„ ์ด์šฉํ•˜์—ฌ youtube ์‚ฌ์ดํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ

๐Ÿ“ ์„ค๋ช…

  • react router๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ ํŠœ๋ธŒ ์‚ฌ์ดํŠธ ๊ตฌํ˜„


โœ’๏ธ ์ฝ”๋“œ ์ž‘์„ฑ

์ž…๋ ฅ

App.js

import './App.css';
import { Outlet } from "react-router-dom";
import SearchHeader from './components/SearchHeader';

function App() {
  return (
    <>
      <SearchHeader />
      <Outlet />
    </>
  );
}

export default App;



index.js

import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./index.css";
import App from "./App";
import NotFound from "./pages/NotFound";
import Videos from "./pages/Videos";
import VideoDetail from "./pages/VideoDetail";

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <NotFound />,
    children: [
      { index: true, element: <Videos /> }, // ์ฒ˜์Œ ์„ค์ •
      { path: "/videos", element: <Videos /> },
      { path: "/videos/watch/:videoId", element: <VideoDetail /> },
      { path: "/videos/:keyword", element: <Videos /> },
    ],
  },
]);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    {/* element์— ์ด๋ฏธ App์ด ์žˆ์Œ */}
    <RouterProvider router={router} />
  </React.StrictMode>
);



  • pages ํด๋”
    Videos.jsx
import React from "react";
import { useParams } from "react-router-dom";

export default function Videos() {
  // const aa = useParams();
  // const bb = aa.keyword
  const { keyword } = useParams();

  console.log("aa? : ", keyword);

  return (
    <div>Videos - {keyword ? `๐Ÿ” ${keyword}` : "๐Ÿ”ฅ ์ธ๊ธฐ๊ธ‰์ƒ์Šน"}</div>
    // ํ˜„์žฌ ์ฃผ์†Œ ๋งˆ์ง€๋ง‰์— ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์„ ๋•Œ / ์—†์„ ๋•Œ ๊ตฌ๋ถ„
  );
}



VideoDetail.jsx

import React from 'react'

export default function VideoDetail() {
  return (
    <div>VideoDetail</div>
  )
}



NotFound.jsx

import React from "react";

export default function NotFound() {
  return (
    <div>
      <h3>์—†๋Š” ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.</h3>
    </div>
  );
}



  • components ํด๋”
    SearchHeader.jsx
import React, { useEffect, useState } from "react";
import { BsYoutube, BsSearch } from "react-icons/bs";
import { Link, useNavigate, useParams } from "react-router-dom";

export default function SearchHeader() {
  const navigate = useNavigate();
  const { keyword } = useParams(); // ์ฃผ์†Œ์ฐฝ์— ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ useEffect์—์„œ ๊ฐ์ง€ํ•˜๊ฒŒ
  const [text, setText] = useState(""); // ๋ฌธ์ž์—ด์„ ๊ฐ€์ ธ์˜ด (input์— ์ž…๋ ฅ๋œ ์ž…๋ ฅ๊ฐ’์„ ์•Œ์•„์˜ค๊ฒŒ)

  const handleSubmit = (e) => {
    e.preventDefault();
    navigate(`/videos/${text}`);
    // setText("");
  };

  // ํ‚ค์›Œ๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค input ๊ฐ’ ์—…๋ฐ์ดํŠธ
  useEffect(() => {
    setText(keyword || "");
  }, [keyword]);

  return (
    <header className="flex ">
      <Link to="/">
        {/* aํƒœ๊ทธ์™€ ๋™์ผํ•œ ์—ญํ• ์„ ํ•จ */}
        <BsYoutube />
        <h1>Youtube</h1>
      </Link>

      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="๊ฒ€์ƒ‰"
          value={text}
          onChange={(e) => setText(e.target.value)} // ํ•ด๋‹น ๊ฐ’์ด setText ์•ˆ์œผ๋กœ ๋“ค์–ด๊ฐ
        />
        <button>
          <BsSearch />
        </button>
      </form>
    </header>
  );
}



์ถœ๋ ฅ

  • ์ด๋ฏธ์ง€๋กœ ๋Œ€์ฒด


๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ & ๋„์›€์ด ๋˜๋Š” ๋งํฌ






profile
๊ณต๋ถ€ํ•˜๋Š” ๋ฒจ๋กœ๊ทธ

0๊ฐœ์˜ ๋Œ“๊ธ€