React- DB & React
-
저번 시간에는 DB 백엔드 서버와 연결하지 않고 임의의 데이터로 리액트를 연습했다면 이번주 부터는 DB와 연결해서 프론트는 리액트로 출력하자
- <기초적인 리액트는="" 유튜브="" 강의를="" 통해서="" 학습할것=""> 기초적인>
- 일단 server 와 ex05 파일을 만든다 server는 DB를 관리, ex05는 리액트로 연결시켜줄것이다.
- 홈과, 주소관리, 상품관리 메뉴를 만든다.
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 페이지를 만들어서 페이지도 이동가능하게 구현해두었다.
-
추가되면 좋을만한것
- 상품명, 이름을 클릭했을때 정보 (read) 만들기 (이후에 할예정)
- 페이지를 더 깔끔하게.
끝!
댓글남기기