[ JavaScript / React ] js, bootswatch 메뉴바 디자인 적용 및 map() 함수 사용

2024. 5. 6. 14:57· FRONT-END/└ React

환경 : Visual Studio Code

 

 

1) 먼저 프로젝트 생성 및 부트 스트랩 설치

npm create-react-app demo05 --skip-git
cd demo05
npm i bootstrap
npm i bootswatch
npm start

 

 

2) index.js 파일에 임포트 추가

 

    - 추가한 코드

//bootstrap
import "bootstrap/dist/css/bootstrap.min.css";
import "bootswatch/dist/cosmo/bootstrap.min.css";
import './index.css'; //위치 변경

 

    - index.js 전체 코드

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';

//bootstrap
import "bootstrap/dist/css/bootstrap.min.css";
import "bootswatch/dist/cosmo/bootstrap.min.css";
import './index.css';

import "bootstrap"; //js는 경로를 생략해도 기본 경로로 설정됨
import { HashRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    {/* 리액트 라우터를 사용하는 영역을 지정 */}
    <HashRouter>
    <App />
    </HashRouter>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

 

3) 메뉴바를 다룰 js 파일 생성 및 메인 js 파일 수정

components 폴더를 만들고 Menu.js 파일을 만든다. 이후 App.js에 임포트 시킨다

 

    - Menu.js : 기본 구조 잡아두기

//import

//function
function Menu() {

    return (
        <>
        </>
    );
}

//export
export default Menu;

 

    - App.js

import logo from './logo.svg';
import './App.css';
import Menu from './components/Menu';

function App() {
  return (
    <>
      <Menu/>
    </>
  );
}

export default App;

 

 

4) bootswatch 적용

해당 링크(https://bootswatch.com/)에서 원하는 디자인의 네비게이션 바 선택 및 코드 복사 후 Menu.js 에 붙여넣기

 

아래는 전체코드를 복사한 후 알맞게 변경한 코드이다

    - Menu.js

//import
import {NavLink} from "react-router-dom";

//function
function Menu() {

    return (
        <>
            <nav className="navbar navbar-expand-lg bg-light" data-bs-theme="light">
                <div className="container-fluid">
                    {/* React에서는 페이지간 이동을 NavLink 태그로 한다 */}
                    <NavLink className="navbar-brand" to="/">NavBar</NavLink>
                    {/* <a className="navbar-brand" href="#">NavBar</a> */}
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
                        <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarColor03">
                        <ul className="navbar-nav me-auto">
                            <li className="nav-item dropdown">
                                <a className="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">State 예제</a>
                                <div className="dropdown-menu">
                                    <NavLink className="dropdown-item" to="/ex01">예제1번</NavLink>
                                    <NavLink className="dropdown-item" to="/ex01">예제2번</NavLink>
                                    {/* <a className="dropdown-item" href="#">예제1번</a>
                                    <a className="dropdown-item" href="#">예제2번</a> */}
                                </div>
                            </li>
                        </ul>
                        <form className="d-flex">
                            <input className="form-control me-sm-2" type="search" placeholder="Search" />
                                <button className="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
                        </form>
                    </div>
                </div>
            </nav>
        </>
    );
}

//export
export default Menu;

     (+) 맨 처음에 코드를 가져와 붙여넣기만 했을 경우 하위 메뉴가 작동하지 않는다. 이는 js 기능이 없기 때문인데, 이를 해결하기 위해선 js를 임포트 해줘야 한다! 

    -  index.js

import "bootstrap"; //js는 경로를 생략해도 기본 경로로 설정됨

 

     (+) 페이지 간 이동(메뉴 클릭 시 이동)을 위해선 react-router를 설치해줘야 한다!

         참고 : https://www.npmjs.com/search?q=react-router

         cmd에서 아래와 같은 명령어를 입력한다

npm i react-router
npm i react-router-dom

        

          그리고, 이 이동이 정말 써먹히려면 <HashRouter></HashRouter> 혹은 <BrowserRouter></ BrowserRouter >를 적용시켜야 한다!! 즉, 리액트 라우터를 사용하는 영역을 지정해줘야 한다.

     - index.js

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    {/* 리액트 라우터를 사용하는 영역을 지정 */}
    <HashRouter>
    <App />
    </HashRouter>
  </React.StrictMode>
);

막간을 이용한 HashRouter/BrowserRouter 차이

 

 

     (+) React에선 <a></a> 태그가 아닌 <NavLink></NavLink> 태그로 페이지 이동을 한다. 

          <NavLink className="" to="/">

     (+) 예제 1번/ 예제 2번을 눌렀을 때 주소의 변화는 다음과 같다


 

이제 유기적인 이동이 가능한 페이지를 구체화 시켜보자~!!

 

    - App.js

import logo from './logo.svg';
import './App.css';
import Menu from './components/Menu';
import Home from './components/Home';
import Ex01 from './components/Ex01';
import Ex02 from './components/Ex02';
import { Route, Routes } from 'react-router';

function App() {
  return (
    <>
      {/* 메뉴 배치 */}
      <Menu/>

      {/* 메뉴를 눌렀을 때 나올 화면 배치 */}
      <div className='container-fluid my-5 '>
        <div className='row'>
          <div className='col-sm-10 offset-sm-1'>
            
            {/* 
                메뉴를 눌렀을 때 나올 화면 배치 
                - path를 통해 주소를 설정
                - element를 통해 연결될 화면을 설정
            */}
            <Routes>
              <Route path='/' element={<Home/>}/>
              <Route path='/ex01' element={<Ex01/>}/>
              <Route path='/ex02' element={<Ex02/>}/>
            </Routes>

          </div>
        </div>
      </div>
    </>
  );
}

export default App;

     (+) <Routes></Routes> 태그로 감싸 이동할 페이지의 경로를 설정해주자 

           <Route path='#' element={}>

{/* 
메뉴를 눌렀을 때 나올 화면 배치 
- path를 통해 주소를 설정
- element를 통해 연결될 화면을 설정
*/}
<Routes>
<Route path='/' element={<Home/>}/>
<Route path='/ex01' element={<Ex01/>}/>
<Route path='/ex02' element={<Ex02/>}/>
</Routes>

 

   - Home.js


function Home(){

    return(
        <>
            <h1>메인 페이지</h1>
        </>
    );
}

export default Home;

 

    - Menu.js (위 코드와 동일)

 

다음 Ex01.js와 Ex02.js 는 점보트론 페이지를 만들어서 중복되는 부분의 코드는 가져오도록 구현할 것이다. 

 

    - Jumbotron.js

//페이지의 제목 역할을 하는 컴포넌트

function Jumbotron(props){ //props는 상위 컴포넌트에서 전달되는 값(=파라미터)

    return(
        <>
            <div className="row">
                <div className="col">
                    <div className="p-4 bg-dark text-light rounded">
                        <h1>{props.title}</h1>
                        <p>{props.content}</p>
                    </div>
                </div>
            </div>
        </>
    );
}

export default Jumbotron;

     (+) props로 값으 전달 받아 해당 위치에 넣어준다. 

 

 

    - Ex01.js

import { useState } from "react";
import Jumbotron from "./Jumbotron";


function Ex01() {

    //state
    const [students, setStudents] = useState([
        { studentNo: 1, studentName: "손흥민", studentScore: 100 },
        { studentNo: 2, studentName: "조규성", studentScore: 77 },
        { studentNo: 3, studentName: "이강인", studentScore: 69 },
        { studentNo: 4, studentName: "박지성", studentScore: 47 },
        { studentNo: 5, studentName: "설영우", studentScore: 20 },
    ]);

    return (
        <>
            <Jumbotron title="예제1번" content="객체 배열 State" />

            {/* ES6에서 배열을 변환할 때는 map 함수를 사용한다 */}
            {students.map((student, index) => (
                <div>
                    <span>{student.studentNo}</span>
                    <span>{student.studentName}</span>
                    <span>{student.studentScore}점</span>
                </div>
            ))}
        </>
    );
}

export default Ex01;

     (+) Jumbotron.js에 값을 넘겨주는 코드는 다음과 같다

<Jumbotron title="예제1번" content="객체 배열 State" />

 

     (+) map 메소드와 자바스크립의 <forEach> 태그를 비교해서 이해해보자

 {/*  
    <c:forEach var="student" items="${students}">
        <div>
            <span>${student.studentNo}</span>
            <span>${student.studentName}</span>
            <span>${student.studentScore}점</span>
        </div>
    </c:forEach>
*/}
    {students.map((student, index) => (
        <div>
            <span>{student.studentNo}</span>
            <span>{student.studentName}</span>
            <span>{student.studentScore}점</span>
        </div>
    ))}

 

   - Ex02.js

import { useState } from "react";
import Jumbotron from "./Jumbotron";

function Ex02(){

    //state
    const [toys, setToys] = useState([
        {toySerial:1, toyName:"뽀로로", toyPrice:15000},
        {toySerial:2, toyName:"크롱", toyPrice:12000},
        {toySerial:3, toyName:"루피", toyPrice:18000},
        {toySerial:4, toyName:"패티", toyPrice:16000},
        {toySerial:5, toyName:"포비", toyPrice:22000},
        {toySerial:6, toyName:"루디", toyPrice:21000},
        {toySerial:7, toyName:"에디", toyPrice:12000},
        {toySerial:8, toyName:"똘똘이", toyPrice:11500},
        {toySerial:9, toyName:"앵두", toyPrice:10000},
        {toySerial:10, toyName:"달님이", toyPrice:22500},
    ]);

    return(
        <>
            <Jumbotron title="예제2번" content="두 번째 예제"/>

            <div className="row mt-4">
                <div className="col">
                    <table className="table table-striped">
                        <thead>
                            <tr>
                                <th>번호</th>
                                <th>상품명</th>
                                <th>판매가</th>
                            </tr>
                        </thead>
                        <tbody>
                            {toys.map((toy =>(
                                <tr>
                                    <td>{toy.toySerial}</td>
                                    <td>{toy.toyName}</td>
                                    <td>{toy.toyPrice}원</td>
                                </tr>
                            )))}
                        </tbody>
                    </table>
                </div>
            </div>
        </>
    );
}

export default Ex02;

 

   - 예제2번 출력결과


 

 

 

 

 

 

 

개인 공부 기록용입니다:)

 

728x90