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>
);
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>
);
}
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>
);
}