본문 바로가기

react

리액트 _1_만개의레시피 리액트버전

*HOOKS

 - state(데이터)관리 ==>useState()

 - 화면 출력 전에 데이터 읽기 => useEffect(()=>{},[])

                                           => 비동기화 ===> redux-thunk

                                                      redux-saga

 - useCallback: function을 기억함 => 싱글턴

 - React.memo ==> useMemo()

 

*전역변수: useContext(),

 리덕스: useDispatch(이벤트를 통해 데이터 받기), useSelector(이벤트 컨트롤러), useReducer(디스패치로 받은 값 넘겨주기)

 

1. 새프로젝트를 만든다.

2. package.json에다가 구성을 해준다.

"axios": "^0.19.2", --파일 받을 때 사용하는 것
"express": "^4.17.1",
"mongodb": "^3.5.8",
"path": "^0.12.7",
"request": "^2.88.2",
"xml2js": "^0.4.23",  --xml을 json으로 변경하는 것
"react-router": "^5.2.0", --라우터 할 때 사용하는 것
"react-router-dom": "^5.2.0"--라우터 할 때 사용하는 것

3. 디렉토리를 하나 생성한다 (이름:components)

안에 js파일을 생성한다. 

*부가적으로 header(메뉴역할)을 추가해준다. 

4. header(메뉴역할)를 먼저 만든다.

   css 디자인과 구성은 아래 링크에서 가져온다. 반드시 링크도 받아올 것.

https://www.w3schools.com/bootstrap/bootstrap_navbar.asp

링크연결을 위해 NavLink를 import 한다. {}은 뒤에있는 라이브러리에서 여러개를 가져올 때 사용한다. 

<a>태그를 NavLink로 바꿔준다. href는 to로 바꿔서 링크연결을 해준다. 

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

//render()
export  default function Header() {
    /*
    * to={"/"}  : http://localhost:3000/ 이걸로 접속한다는 의미
    *
    * */
    return(
        <nav className="navbar navbar-inverse">
            <div className="container-fluid">
                <div className="navbar-header">
                    <NavLink className="navbar-brand" to={"/"}>STST Recipe</NavLink>
                </div>
                <ul className="nav navbar-nav">
                    <li className="active"><NavLink exact to={"/"}>레시피</NavLink></li>
                    <li><NavLink to={"/chef"}>쉐프</NavLink></li>
                    <li><NavLink to={"/news"}>레시피뉴스</NavLink></li>
                    <li><NavLink to={"/find"}>레시피검색</NavLink></li>
                </ul>
            </div>
        </nav>
    )
}

 

to 앞에 exact를 붙이면 default로 설정이 된다. 

 

5. App.js에서 시작하기 때문에 여기서 만든 js 파일을 모아둔다.

BrowserRouter,Route,Switch를 import 한다. 

import {BrowserRouter as Router, Route,Switch} from "react-router-dom";

사용자가 사이트 주소를 주면 route가 받고 선택한 내용을 Switch가 받고 그 선택을 하는 애는 BrowserRouter다.

import React from 'react';
import {BrowserRouter as Router, Route,Switch} from "react-router-dom";
import Header from "./components/Header";
import Recipe from "./components/Recipe";
import RecipeDetail from "./components/RecipeDetail";
import Chef from "./components/Chef";
import ChefDetail from "./components/ChefDetail";
import RecipeFind from "./components/RecipeFind";
import RecipeNews from "./components/RecipeNews";

function App() {
  return (
      <Router>
        <Header/>
        <div className={"container-fluid"}>
          <div className={"jumbotron"}>
            <Switch>
              <Route exact path={"/"} component={Recipe}/>
              <Route path={"/recipe_detail"} component={RecipeDetail}/>
              <Route path={"/chef"} component={Chef}/>
              <Route path={"/chef_detail"} component={ChefDetail}/>
              <Route path={"/news"} component={RecipeNews}/>
              <Route path={"/find"} component={RecipeFind}/>
            </Switch>
          </div>
        </div>
      </Router>
  );
}

export default App;

 

결과) 메뉴를 누르면 페이지 글이 달라진다. 

6. spring으로 출력하면 좋겠지만 상황이 안되므로 recipe-server를 만들어서 화면에 출력해주려고 한다. 

bind() => IP PORT 연결해주는 역할
listen() => 대기상태
accept() => 클라이언트가 접속을 했을 때 처리하는 부분
const express=require("express")
//라이브러리 로드
//서버 생성
const app=express();
//서버를 구동
/*
    bind() => IP와 PORT 연결해주는 역할
    listen() => 대기상태
    accept() => 클라이언트가 접속을 했을 때 처리하는 부분
 */
app.listen(3355,()=>{
    console.log("Server Start...","http://localhost:3355")
})
app.all('/*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});
//클라이언트와 통신하는 부분
//사용자(클라이언트)의 URI를 받아옴 => 사용자가 이용할 수 있는게 브라우저밖에 없어서 이걸 가져오는 것.URI 주소는 다 다르기 때문에 이걸로 구분
//mongoDB 연결
const  Client = require("mongodb").MongoClient;
//mongoDB connection
app.get('/recipe_',(request,response)=>{
    //request = 사용자가 보내준 요청 정보
    //요청 처리
    //response = 결과를 전송
    var page=request.query.page; //request.getParameter("page")
    var rowSize = 12;
    var skip=(page*rowSize)-rowSize;

    var url="mongodb://211.238.142.181:27017"; //몽고디비 주소
    Client.connect(url, (err,client)=>{
        var db = client.db('mydb');
        //db.collection('recipe').find({})  == select * from recipe
        //find({"title":{"$regex":".*"+값}} == select * from recipe where title Like '%값%'
        db.collection('recipe').find({}).skip(skip).limit(rowSize).toArray((err,docs)=>{ //데이터가 배열이 아닌 낱개로 들어가서 이렇게 해줌
            //요청한 사용자에게 값 보내기
            response.json(docs);
            client.close();
        })

    });


})

7. >node recipe-server 를 터미널에 쳐서 서버를 돌린다.

http://localhost:3355/recipe?page=1 를 들어가면 12개씩 출력된다. 

8. Recipe.js를 작성한다.

import React, {useState,useEffect} from "react";
import axios from 'axios';


export default function Recipe() {
        const [recipe,setRecipe]=useState([]); //배열로 받아야 하기 때문에 이렇게 작성
        const [page,setPage]=useState(1);

        useEffect(()=>{
                //서버를 연결해서 데이터를 읽어온 후 setRecipe에 저장
                axios.get('http://localhost:3355/recipe',{
                        params:{
                                page:page //http:localhost:3355/recipe?page=1 과 동일한 형태
                        }}).then((result)=>{ //배열 값이 result에 저장된 상태
                                setRecipe(result.data);
                })
        },[]) //deps를 주어야 한번만 된다.

        const html = recipe.map((m)=>
            <div className="col-md-4">
                    <div className="thumbnail">
                            <img src={m.poster} alt="Lights" style={{"width":"100%"}}/>
                                    <div className="caption">
                                            <p style={{"fontSize":"9pt"}}>{m.title}</p>
                                            <sub style={{"color":"gray"}}>{m.chef}</sub>
                                    </div>
                    </div>
            </div>)
        //출력할 데이터 모아서 return에 전송
        return(
            <div className={"row"}>
                    {html}
            </div>

        )
}

결과) 터미널 하나를 더 열어서 실행시키면 이렇게 화면이 뜬다. 

 

반응형