λ°λ‘κ°κΈ° : https://light9639.github.io/React-Helmet-TypeScript/
β¨ React-Helmet-Async λΌμ΄λΈλ¬λ¦¬λ₯Ό μ΄μ©νμ¬ λ§λ μμ μ λλ€. β¨
- React μμ±
npm create-react-app my-app
# or
yarn create react-app my-app
- viteλ₯Ό μ΄μ©νμ¬ νλ‘μ νΈλ₯Ό μμ±νλ €λ©΄
npm create vite@latest
# or
yarn create vite
- ν°λ―Έλμμ μ€ν ν νλ‘μ νΈ μ΄λ¦ λ§λ ν React μ ν, Typescirpt-SWC μ ννλ©΄ μμ± μλ£.
- μ΄ νλ‘μ νΈλ₯Ό λ§λ€λ €λ©΄ νμν μ¬λ¬ λΌμ΄λΈλ¬λ¦¬λ€μ μ€μΉν΄μΌ νλ€. λ°λΌμ
react-helmet-async
,sass
,react-router-dom
μ μ€μΉνλ€.
$ npm install react-helmet-async sass react-router-dom
# or
$ yarn add react-helmet-async sass react-router-dom
react-router-dom
μμBrowserRouter
μimport
ν λ€App
μ»΄ν¬λνΈλ₯Ό κ°μΈμ λΌμ°ν κΈ°λ₯μ μΆκ°νλ€.
import { BrowserRouter } from 'react-router-dom'
<BrowserRouter>
<App />
</BrowserRouter>
react-helmet-async
λ₯Ό μ΄μ©νμ¬link
,title
μ μμ±νκ³Hello.tsx
λ‘props
λ₯Ό μ μ‘νμ¬title
λͺ μ΄ λ°λλλ‘ μ€μ νλ€.react-router-dom
μLink
,Routes
,Route
μ μ΄μ©νμ¬ λΌμ°ν κΈ°λ₯ ꡬν.- λ¬Έμ μλ¨μ
Header
μ»΄ν¬λνΈλ₯Ό λ£μ΄μLink
λ₯Ό ν΅ν΄ νμ΄μ§ μ΄λ μν€κ² νλ€.
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import HelmetImg from './assets/Helmet.png'
import { Helmet, HelmetProvider } from "react-helmet-async";
import Hello from "./components/Hello";
import Detail from "./components/Detail";
import { Link, Routes, Route } from 'react-router-dom'
import Header from './components/Header';
import './App.scss'
export default function App(): JSX.Element {
return (
<div className="App">
<Header />
<div>
<a href="https://www.npmjs.com/package/react-helmet-async" target="_blank">
<img src={HelmetImg} className="logo" alt="Helmet logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<HelmetProvider>
<div>
<Helmet>
<link rel="icon" type="image/svg+xml" href={HelmetImg} />
<title>React-Helmet-Async</title>
<link rel="canonical" href="https://www.tacobell.com/" />
</Helmet>
<Routes>
<Route path="/" element={<Hello name="React-Helmet-Async" />} />
<Route path="/detail/:id" element={<Detail name="Detail" />} />
<Route path="*" element={<Hello name="This is Error Page" />} />
</Routes>
<h2>λ§ν¬λ₯Ό ν΄λ¦νλ©΄ μ΄λ¦κ³Ό Titleλͺ
μ΄ λ³κ²½λ©λλ€. {"\u2728"}</h2>
</div>
</HelmetProvider>
</div>
)
}
index.scss
μ@mixin
μ μ΄μ©ν λ°μν ν¨μλ₯Ό μΆκ°νλ€.
@mixin mobile {
@media (max-width: 767px) {
@content;
}
}
h1 {
font-size: 1.75rem;
line-height: 1.1;
@include mobile {
font-size: 1.35rem;
}
}
h2 {
margin-top: 30px;
font-size: 1.1rem;
@include mobile {
margin-top: 25px;
font-size: 0.9rem;
}
}
App.scss
μ@mixin
μ μ΄μ©ν λ°μν ν¨μμ,Header
λΆλΆμ μ€νμΌλ§μ μΆκ°νλ€.logo
νΈλ²μ ν¨κ³Όμ λ°μν μ€νμΌλ§ μΆκ°.
@mixin mobile {
@media (max-width: 767px) {
@content;
}
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
margin: 75px 0 30px;
@include mobile {
height: 5rem;
margin: 60px 0 10px;
}
&:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
&.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
}
.Header {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
margin-bottom: 25px;
gap: 25px;
background-color: #000;
width: 100%;
padding: 20px 0;
@include mobile {
flex-wrap: wrap;
}
a {
font-size: 1rem;
color: #fff;
font-weight: 600;
transition: .5s;
@include mobile {
font-size: 0.9rem;
}
&:hover,
&:focus {
color: skyblue;
}
}
}
App.tsx
μμ<Route path="/detail/:id />
λ₯Ό μ¬μ©νμ¬/detail/2
λ‘ μ΄λμtitle
μ΄ Detail2 Pageμ΄ λλλ‘ μ€μ νλ€.useParams()
λ₯Ό μ¬μ©νμ¬ κ° νμ΄μ§λ§λ€μ μ«μκ°μ κ°μ Έμ¨ ν ν μ€νΈμtitle
κ°μ λ£λλ€.
import * as React from "react";
import { useParams } from 'react-router-dom';
import { Helmet, HelmetProvider } from "react-helmet-async";
interface Props {
name: string;
}
export default ({ name }: Props) => {
let { id } = useParams();
console.log(id)
return (
<React.Fragment>
<Helmet>
<title>{name}{id} Page</title>
</Helmet>
<h1>Hello {name} {id}!</h1>
</React.Fragment>
)
}
- μλ¨μ Header μ»΄ν¬λνΈλ₯Ό λ£μ΄μ
Link
λ₯Ό ν΅ν΄ νμ΄μ§ μ΄λμ κ°λ₯νκ² νλ€.
import React from 'react'
import { Link } from 'react-router-dom'
export default function Header(): JSX.Element {
return (
<div className='Header'>
<Link to="/">Home</Link>
<Link to="/detail/1">Detail1</Link>
<Link to="/detail/2">Detail2</Link>
<Link to="/detail/3">Detail3</Link>
<Link to="Error">Error</Link>
</div>
)
}
App.tsx
μμprops
λ‘ μ λ¬λ°μ κ°λ€μ΄title
λͺ μ μ λ¬λλλ‘ λ§λ€κ³h1
νκ·Έ μμλ λ€μ΄κ°λλ‘ μ€μ νλ€.
import * as React from "react";
import { useParams } from 'react-router-dom';
import { Helmet } from "react-helmet-async";
interface Props {
name: string;
}
export default ({ name }: Props) => {
return (
<React.Fragment>
<Helmet>
<title>{name} Page</title>
</Helmet>
<h1>Hello {name}</h1>
</React.Fragment>
)
}