Frontend ๐Ÿ“š/React

[์ฝ”๋”ฉ์• ํ”Œ] ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ Part2 - ์ปดํฌ๋„ŒํŠธ, ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ, usenavigate()

leejaejae 2023. 10. 17. 15:47
// data.js ํŒŒ์ผ

let data = [
  {
    id : 0,
    title : "White and Black",
    content : "Born in France",
    price : 120000
  },

  {
    id : 1,
    title : "Red Knit",
    content : "Born in Seoul",
    price : 110000
  },

  {
    id : 2,
    title : "Grey Yordan",
    content : "Born in the States",
    price : 130000
  }
] ;
export default data
// App.js ํŒŒ์ผ

import data from './data.js';

function App(){
  let [shoes] = useState(data);
  return (
    <div className="App">
      (์ƒ๋žต)
      <div className="container">
        <div className="row">
          <div className="col-md-4">
            <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="80%" />
            <h4>{ shoes[0].title }</h4>
            <p>{ shoes[0].price }</p>
          </div>
          <div className="col-md-4">
            <img src="https://codingapple1.github.io/shop/shoes2.jpg" width="80%" />
            <h4>์ƒํ’ˆ๋ช…</h4>
            <p>์ƒํ’ˆ์ •๋ณด</p>
          </div>
          <div className="col-md-4">
            <img src="https://codingapple1.github.io/shop/shoes3.jpg" width="80%" />
            <h4>์ƒํ’ˆ๋ช…</h4>
            <p>์ƒํ’ˆ์ •๋ณด</p>
          </div>
        </div>
      </div>
    </div>
  )
}

}

 
 
๐Ÿ’‍โ™€๏ธ html ๊ธด ๋ถ€๋ถ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค์–ด๋ณด๊ธฐ

function App(){
  return (
    <div className="App">
      (์ƒ๋žต)
      <div className="container">
        <div className="row">
          <Card/>
          <Card/>
          <Card/>
        </div>
      </div>
    </div>
  )
}

function Card(){
  return (
    <div className="col-md-4">
      <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="80%" />
      <h4>์ƒํ’ˆ๋ช…</h4>
      <p>์ƒํ’ˆ์ •๋ณด</p>
    </div>
  )
}


๐Ÿ’‍โ™€๏ธ shoes์— ์žˆ๋˜ ๊ฑฐ Card ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ๊ฝ‚์•„๋„ฃ๊ธฐ

// function App ๋‚ด๋ถ€

<Card shoes={shoes[0]} i={1} />
<Card shoes={shoes[1]} i={2} />
<Card shoes={shoes[2]} i={3} />
function Card(props){
  return (
    <div className="col-md-4">
      <img src={'https://codingapple1.github.io/shop/shoes' + props.i + '.jpg'} width="80%" />
      <h4>{ props.shoes.title }</h4>
      <p>{ props.shoes.price }</p>
    </div>
  )
}


๐Ÿ’‍โ™€๏ธ Detail ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

function Detail(){
  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-6">
          <h4 className="pt-5">์ƒํ’ˆ๋ช…</h4>
          <p>์ƒํ’ˆ์„ค๋ช…</p>
          <p>120000์›</p>
          <button className="btn btn-danger">์ฃผ๋ฌธํ•˜๊ธฐ</button> 
        </div>
      </div>
    </div> 
  )
}

export default Detail
// App.js ์—์„œ ํ™œ์šฉ

import Detail from './routes/Detail.js'

function App(){
  return (
    (์ƒ๋žต)
    <Route path="/detail" element={ <Detail/> } />
  )
}

 
 

โœ๏ธ ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ

โœ๏ธ react-router-dom ์„ค์น˜
- ํ„ฐ๋ฏธ๋„ ์—ด์–ด์„œ npm install react-router-dom@6 ์ž…๋ ฅํ•ด์„œ ์„ค์น˜
- ์…‹ํŒ…์€ index.js ํŒŒ์ผ๋กœ ๊ฐ€์„œ import~ gkrh <BrowserRouter> ์ด๊ฑธ๋กœ <App />์„ ๊ฐ์‹ผ๋‹ค.

import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
      <BrowserRouter>
        <App />
      </BrowserRouter>
  </React.StrictMode>
);


โœ๏ธ ๋ผ์šฐํ„ฐ๋กœ ํŽ˜์ด์ง€ ๋‚˜๋ˆ„๋Š” ๋ฒ•
- url ๊ฒฝ๋กœ๋งˆ๋‹ค ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์œผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑ

// App.js

import { Routes, Route, Link } from 'react-router-dom'

function App(){
  return (
    (์ƒ๋žต)
    <Routes>
      <Route path="/" element={
        <>
        <div className="main-bg"></div>
        <div className="container">
          <div className="row">
            { shoes.map((a, i)=>{
              return <Card shoes={shoes[i]} i={i} ></Card>
             })}
          </div>
        </div> 
        </>
      } /> 
      <Route path="/detail" element={ <div>์ƒ์„ธํŽ˜์ด์ง€์ž„</div> } />
      <Route path="/about" element={ <div>์–ด๋ฐ”์›ƒํŽ˜์ด์ง€์ž„</div> } />
    </Routes>
  )
}

1. ์šฐ์„  ์ƒ๋‹จ์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ปดํฌ๋„ŒํŠธ import ํ•ด์˜ค๊ณ 
2. <Routes> ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์— <Route> ์ž‘์„ฑ
3. <Route path="/๊ฒฝ๋กœ" element={ <๋ณด์—ฌ์ค„html> } /> ์ž‘์„ฑ

โœ๏ธ ํŽ˜์ด์ง€ ์ด๋™ ๋ฒ„ํŠผ
- ๋งํฌ๋ฅผ ํด๋ฆญํ•ด ์ด๋™

import { Link } from 'react-router-dom';

<Link to="/">ํ™ˆ</Link>
<Link to="/detail">์ƒ์„ธํŽ˜์ด์ง€</Link>


โœ๏ธ ํŽ˜์ด์ง€ ์ด๋™๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ: usenavigate()
- Link ์“ฐ๋ฉด ๋ชป์ƒ๊ฒผ์Œ

import { Routes, Route, Link, useNavigate, Outlet } from 'react-router-dom'

function App(){
  let navigate = useNavigate()
  
  return (
    (์ƒ๋žต)
    <button onClick={()=>{ navigate('/detail') }}>์ด๋™๋ฒ„ํŠผ</button>
  )
}

- -1 ๋„ฃ์œผ๋ฉด ๋’ค๋กœ 1๋ฒˆ ๊ฐ€๊ธฐ, 2 ๋„ฃ์œผ๋ฉด ์•ž์œผ๋กœ 2๋ฒˆ ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ

โœ๏ธ 404 ํŒจ์ด์ง€

 <Route path="*" element={ <div>์—†๋Š”ํŽ˜์ด์ง€์ž„</div> } />

- * ๊ฒฝ๋กœ๋Š” ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ๋œปํ•ด์„œ ์œ„์— ๋งŒ๋“ค์–ด๋‘” /detail ์ด๋Ÿฐ๊ฒŒ ์•„๋‹Œ ์ด์ƒํ•œ ํŽ˜์ด์ง€ ์ ‘์†์‹œ * ๊ฒฝ๋กœ๋กœ ์•ˆ๋‚ด

โœ๏ธ ์„œ๋ธŒ๊ฒฝ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” nested routes

<Route path="/about" element={ <About/> } >  
  <Route path="member" element={ <div>๋ฉค๋ฒ„๋“ค</div> } />
  <Route path="location" element={ <div>ํšŒ์‚ฌ์œ„์น˜</div> } />
</Route>

- <Route> ์•ˆ์— <Route> ๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์„ Nested routes ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
- ์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด /about/member๋กœ ์ ‘์†์‹œ <About> & <div>๋ฉค๋ฒ„๋“ค></div>์„ ๋ณด์—ฌ์ฃผ๊ณ 
- /about/location์œผ๋กœ ์ ‘์†์‹œ <About> & <div>ํšŒ์‚ฌ์œ„์น˜</div> ์„ ๋ณด์—ฌ์ค€๋‹ค.
- ์‹ค์ œ๋กœ ์œ„ ์ฝ”๋“œ๋Š” /about/memeber๋กœ ์ ‘์†์‹œ <About>์•ˆ์— <div>๋ฉค๋ฒ„๋“ค</div>์„ ๋ณด์—ฌ์ค€๋‹ค.
- <About> ์ปดํฌ๋„ŒํŠธ ์•ˆ์— <div>๋ฅผ ์–ด๋””๋‹ค ๋ณด์—ฌ์ค„์ง€ ํ‘œ๊ธฐํ•ด์•ผ ์ž˜ ๋ณด์—ฌ์คŒ

function About(){
  return (
    <div>
      <h4>aboutํŽ˜์ด์ง€์ž„</h4>
      <Outlet></Outlet>  <!-- nested routes ์•ˆ์˜ element๋“ค์„ ์–ด๋””์— ๋ณด์—ฌ์ค„์ง€ ํ‘œ๊ธฐํ•˜๋Š” ๊ณณ -->
    </div>
  )
}


โœ๏ธ ์ƒ์„ธํŽ˜์ด์ง€์— ์ƒํ’ˆ๋ช… ๋„ฃ๊ธฐ
- shoes๋ผ๋Š” state์— ์žˆ๋˜ ์ƒํ’ˆ ์ •๋ณด๋“ค์„ Detail ์ปดํฌ๋„ŒํŠธ์— ๋„ฃ์–ด๋ณด์ž.

// App.js
<Route path="/detail" element={ <Detail shoes={shoes}/> }/>  // <Detail> ์“ฐ๋Š” ๊ณณ์—์„œ ์ผ๋‹จ props ์ „์†ก
// Detail.js
<div className="container>
  <div className="row">
    <div className="col-md-6">
      <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
    </div>
    <div className="col-md-6 mt-4">
      <h4 className="pt-5">{props.shoes[0].title}</h4>  <!-- 0๋ฒˆ์งธ ์ƒํ’ˆ -->
      <p>{props.shoes[0].content}</p>
      <p>{props.shoes[0].price}์›</p>
      <button className="btn btn-danger">์ฃผ๋ฌธํ•˜๊ธฐ</button>
    </div>
  </div> 
</div>


โœ๏ธ ์ƒ์„ธํŽ˜์ด์ง€ ์—ฌ๋Ÿฌ๊ฐœ ๋งŒ๋“ค๊ธฐ

<Route path="/detail/:id" element={ <Detail shoes={shoes}/> }/>  <!-- url ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ -->

<!-- ๊ฒฐ๊ณผ: /detail/0 /detail/1 /detail/2 -->

- path ์ž‘๋ช…ํ•  ๋•Œ /:์–ด์ฉŒ๊ตฌ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด "์•„๋ฌด ๋ฌธ์ž"๋ฅผ ๋œปํ•œ๋‹ค.
- ๊ทธ๋ž˜์„œ ์œ„์˜ <Route>๋Š” ๋ˆ„๊ตฐ๊ฐ€ ์ฃผ์†Œ์ฐฝ์— /detail/์•„๋ฌด๊ฑฐ๋‚˜ ์ž…๋ ฅํ–ˆ์„ ๋•Œ <Detail> ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ๋‹ฌ๋ผ๋Š” ๋œป

โœ๏ธ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋‹ค๋ฅธ ๋‚ด์šฉ ๋ณด์—ฌ์ฃผ๊ธฐ

import { useParams } from 'react-router-dom'

function Detail(){
  let {id} = useParams();  // /:url ํŒŒ๋ผ๋ฏธํ„ฐ ์ž๋ฆฌ๊ฐ€ ์œ ์ €๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
  console.log(id)
  
  return (
    <div className="container>
      <div className="row">
        <div className="col-md-6">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-6 mt-4">
        <h4 className="pt-5">{props.shoes[id].title}</h4>
        <p>{props.shoes[0].content}</p>
        <p>{props.shoes[0].price}์›</p>
        <button className="btn btn-danger">์ฃผ๋ฌธํ•˜๊ธฐ</button>
      </div>
    </div>
  </div>
  )
}



๋ณธ ํฌ์ŠคํŒ…์€ << React ๋ฆฌ์•กํŠธ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ๊นŒ์ง€! >> ๊ฐ•์˜๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.