• 저번 시간에는 DB 백엔드 서버와 연결하지 않고 임의의 데이터로 리액트를 연습했다면 이번주 부터는 DB와 연결해서 프론트는 리액트로 출력하자

  • <기초적인 리액트는="" 유튜브="" 강의를="" 통해서="" 학습할것="">
  • 일단 server 와 ex05 파일을 만든다 server는 DB를 관리, ex05는 리액트로 연결시켜줄것이다.
  1. 홈과, 주소관리, 상품관리 메뉴를 만든다.

Home.js

import React from 'react'

const Home = () => {
  return (
    <div>
        <h1>Home</h1>
    </div>
  )
}

export default Home

Address.js

import React, { useEffect, useState } from 'react'
import AddressInsert from './AddressInsert';
import AddressItem from './AddressItem';
import Pagenation from './Pagenation';
import qs from 'qs';

const Address = ({location}) => {
    const query = qs.parse(location.search, {ignoreQueryPrefix:true});
    const page = !query.page ? 1: query.page;
    const [lastPage, setLastPage] = useState(1);

    const [addresses,setAddresses]= useState('');
    const callAPI =()=>{
        fetch('/address/list?page='+page)
        .then(res =>res.json())
        .then(json=>{
            setAddresses(json)
            //전체데이터갯수
            fetch('/address/count')
            .then(res => res.json())
            .then(json=>
                setLastPage(Math.ceil(json.count/5)));    
        });
    }
    
    useEffect(()=>{
        callAPI();
    },[page]);

    if(!addresses){
        return(
            <h2>데이터 로딩중...</h2>
        );
    } 

    return (
        <div className='Address'>
            <h1>주소관리</h1>
            <AddressInsert callAPI={callAPI}/>
            <table>
                <tr className='title'>
                    <td  width={100}>번호</td>
                    <td  width={100}>이름</td>
                    <td  width={200}>전화</td>
                    <td  width={300}>주소</td>
                    <td  width={100}>삭제</td>
                </tr>
                {addresses.map(address=>
                    <AddressItem addr={address} key ={address.id} callAPI={callAPI}/>
                )}
            </table>
            <Pagenation page={page} lastPage={lastPage} path="/address"/>
        </div>
    )
}

export default Address

AddressInsert.js

import React, { useState } from 'react'
import {post} from 'axios'

const AddressInsert = ({callAPI}) => {
    const [addr, setAddr] = useState({
        name:'무기명',
        tel: '010-1111-2222',
        address: '인천'
    });
    const {name,tel, address} =addr;
    const onChange = (e) =>{
        const newAddr={
            ...addr,
            [e.target.name]:e.target.value
        }
        setAddr(newAddr);
    }

    const onSubmit = (e) => {
        e.preventDefault();
        if(name==='' || tel ===''|| address===''){
            alert('내용을 채워주세요!');
            return;
        }
        if(!window.confirm('내용을 등록하실래요?')) return;
        post('/address/insert', addr)
        .then(res=>{
            onReset();
            callAPI();
        });
        
    }

    const onReset= () => {
        setAddr({
            name:'',
            tel:'',
            address:''
        });
    }
    return (
        <form onSubmit={onSubmit}>
            <input placeholder='이름' value={name} name="name" onChange={onChange}/>
            <input placeholder='전화' value={tel} name="tel" onChange={onChange}/>
            <input placeholder='주소'  value={address}  name="address" onChange={onChange}/>
            <div>
                <button type ="submit">주소등록</button>
                <button type="reset" onClick={onReset}>등록취소</button>
            </div>
        </form>
  )
}

export default AddressInsert

AddressItem.js

import React from 'react'
import {post} from 'axios'

const AddressItem = ({addr, callAPI}) => { 
    const {id,name,tel,address} =addr;

    const onDelete = (id) => {
        if(!window.confirm(`${id}를(을) 삭제하실래요?`)) return;
        //db 삭제
        post('/address/delete' ,{"id":id})
        .then(res=>{
            alert('주소삭제 완료!');
            callAPI();
        });
    }
    return (
        <tr>
            <td>{id}</td>
            <td>{name}</td>
            <td>{tel}</td>
            <td>{address}</td>
            <td><button onClick={()=>onDelete(id)} className='sbtn'>삭제</button></td>
        </tr>
    )
}
export default AddressItem

리액트주소관리

Product.js

import React, { useEffect, useState } from 'react'
import Pagenation from './Pagenation';
import ProductInsert from './ProductInsert';
import ProductItem from './ProductItem';
import qs from 'qs';

const Product = ({location}) => {

    const query = qs.parse(location.search, {ignoreQueryPrefix:true});
    const page = !query.page ? 1: query.page;
    const [lastPage, setLastPage] = useState(1);

    const [products, setProduct] =useState('');
    const callAPI =() =>{
      fetch('/product/list?page='+page)
      .then(res=>res.json())
      .then(json=>{
        setProduct(json)
    
        //전체데이터
        fetch('/product/count')
        .then(res=>res.json())
        .then(json=>
          setLastPage(Math.ceil(json.count/5)));
        });
    }

    useEffect(()=>{
      callAPI();
    }, [page]);

    if(!products) {
      return (<h2>데이터 로딩중...</h2>);
    }
    return (
      <div className='Product'>
          <h1>상품관리</h1>
          <ProductInsert callAPI={callAPI} />
          <table>
            <tr class ="title">
                <td width={100}>번호</td>
                <td width={200}>상품명</td>
                <td width={100}>가격</td>
                <td width={100}>판매처</td>
                <td width={100}>등록일</td>
                <td  width={100}>삭제</td>
            </tr>
            {products.map(product=>
                <ProductItem product={product} key ={product.id} callAPI={callAPI}/>
              )}
          </table>
          <Pagenation page={page} lastPage={lastPage}  path="/product"/>
      </div>
    )
}

export default Product

ProductInsert.js

import React, { useState, useRef } from 'react'
import {post} from 'axios'


const ProductInsert = ({callAPI}) => {
    const [product, setProduct] = useState({
        title:'',
        price:'0',
        company:'롯데백화점'
    });
    const {title,price,company} =product;
    const refPrice=useRef(null);

    const onSubmit = e =>{
        e.preventDefault();
        
        if(title ==='' || company===''){
            alert("상품정보를 채워 넣으세요!");
            return;
        }else if(price.replace(/[0-9]/g,'') || price===""){
            refPrice.current.focus();
            alert("가격을 숫자로 입력하세요!")
            return;
        }
        if(!window.confirm('상품을 등록하실래요?')) return;
        //상품 데이터베이스에 등록
        post('/product/insert' , product)
        .then(res=> {
            alert('상품등록성공!');
            callAPI();
        });
    }

    const onChange = e => {
        const newProduct ={
            ...product,
            [e.target.name]:e.target.value
        };
        setProduct(newProduct);
    }

    return (
        <form onSubmit={onSubmit} >
            <input placeholder='상품명'  value={title} name ="title" onChange={onChange}/>
            <input placeholder='상품가격' ref={refPrice} value={price} name ="price" onChange={onChange}/>
            <input placeholder='판매처' value={company} name="company" onChange={onChange}/>
            <div>
                <button type ="submit">상품등록</button>
                <button type ="reset">등록취소</button>
            </div>
        </form>
    )
}

export default ProductInsert

ProductItem.js

import React from 'react'
import {post} from 'axios'

const ProductItem = ({product, callAPI}) => {
	const {id,title, fprice, date, company}= product;

    const onDelete = (id) => {
        if(!window.confirm(`${id}를(을) 삭제하실래요?`)) return;
        //db 삭제
        post('/product/delete' ,{"id":id})
        .then(res=>{
            alert('상품삭제 완료!');
            callAPI();
        });
    }
    return (
        <tr>
            <td>{id}</td>
			<td>{title}</td>
			<td>{fprice}</td>
			<td>{company}</td>
			<td>{date}</td>
            <td><button onClick={()=>onDelete(id)} className='sbtn'>삭제</button></td>
        </tr>
    )
}

export default ProductItem

리액트상품관리

pagination.js

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

const Pagenation = ({page, path, lastPage}) => {
    var intPage = parseInt(page);  
    return (
        <div className='pagenation'>
            <Link to={intPage===1 ?`${path}?page=1`: `${path}?page=${intPage-1}`}>
                <button disabled={intPage===1?true:false} className='btn'>이전</button>
            </Link>
            <span>{intPage}/{lastPage}</span>
            <Link to={intPage===lastPage ?`${path}?page=lastPage`: `${path}?page=${intPage+1}`}>
                <button disabled={intPage===lastPage?true:false}  className='btn'>다음</button>
            </Link>
        </div>
    )
}

export default Pagenation

DB쪽

address

var express = require('express');
var router = express.Router();
var db =require('../db');

/* 주소목록 */
router.get('/list', function(req, res, next) {
    var page=req.query.page;
    var start = (page-1) *5;
    var sql='select * from address order by id desc limit ?, 5';
    db.get().query(sql, [start], function(err, rows){
        res.send(rows);
    })
});

//주소등록
router.post('/insert', function(req,res){
    var name=req.body.name;
    var tel=req.body.tel;
    var address=req.body.address;
    var sql ='insert into address(name, tel, address) values(?,?,?)';
    db.get().query(sql, [name,tel,address], function(err,rows){
        res.sendStatus(200);
    });
});

//주소삭제
router.post('/delete' , function(req,res){
    var id= req.body.id;
    var sql ='delete from address where id =?';
    db.get().query(sql, [id], function(err,rows){
        res.sendStatus(200);
    })
});

//전체데이터갯수
router.get('/count', function(req,res){
    var sql ='select count(*) count from address';
    db.get().query(sql, function(err,rows){
        res.send(rows[0]);
    });
});

module.exports = router;

product.js

var express = require('express');
var router = express.Router();
var db = require('../db');

/* 상품목록 */
router.get('/list', function(req, res, next) {
    var page=req.query.page;
    var start = (page-1) *5;
    var sql = 'select *,date_format(regdate, "%Y-%m-%d") date,format(price,0)fprice from product order by id desc limit ?, 5';
    db.get().query(sql,[start], function(err, rows){
        res.send(rows);
    })
});

//상품등록
router.post('/insert',function(req,res){
    var title =req.body.title;
    var price =req.body.price;
    var company =req.body.company;
    var sql ='insert into product(title, price, company) values(?,?,?)';
    db.get().query(sql, [title,price,company], function(err, rows){
        res.sendStatus(200);
    });
});

//전체데이터갯수
router.get('/count', function(req,res){
    var sql ='select count(*) count from product';
    db.get().query(sql, function(err,rows){
        res.send(rows[0]);
    });
});

//상품삭제
router.post('/delete' , function(req,res){
    var id= req.body.id;
    var sql ='delete from product where id =?';
    db.get().query(sql, [id], function(err,rows){
        res.sendStatus(200);
    })
});
module.exports = router;

  • 상품관리, 주소관리 모두 똑같은기능이다. input으로 주소와 상품을 입력받아서 목록 창에 출력해준다.

  • 그리고 Pagination 페이지를 만들어서 페이지도 이동가능하게 구현해두었다.

  • 추가되면 좋을만한것

    1. 상품명, 이름을 클릭했을때 정보 (read) 만들기 (이후에 할예정)
    2. 페이지를 더 깔끔하게.

끝!

태그:

카테고리:

업데이트:

댓글남기기