- haksa 이어서
// 프로젝트 폴더 진입
C:\data\react>cd haksa
// 프로젝트 dev 모드 스타트
C:\data\react\haksa>yarn dev
- 강좌 목록을 만들어보겠다.
- C:\data\react\haksa\server.js
// 3. 강좌목록 가지고 오기
app.get('/cou/list',(req,res)=>{
var sql = 'select * from view_cou';
con.query(sql,(err,rows)=>{
res.send(rows);
})
})
- C:\data\react\haksa\client\src\component\(new)CourseItem.js
import React from 'react';
const CourseItem = ({course}) => {
const {lcode, lname, hours, instructor, capacity, persons, pname} = course
return (
<tr>
<td>{lcode}</td>
<td>{lname}</td>
<td>{hours}</td>
<td>{instructor}</td>
<td>{pname}</td>
<td>{persons}</td>
<td>{capacity}</td>
</tr>
);
};
export default CourseItem;
- C:\data\react\haksa\client\src\component\(new)CourseList.js
import React, { useEffect, useState } from 'react';
import axios from 'axios'
import CourseItem from './CourseItem';
const CourseList = () => {
const [list, setList] = useState([]);
const callAPI = async() => {
try {
// 주소
const res = await axios.get('/cou/list');
setList(res.data);
} catch (error) {
console.log(error);
}
}
useEffect(()=>{
callAPI();
},[]);
return (
<div>
<table>
<th colSpan={7}>강좌목록</th>
<tr>
<td className="title" width="80">강좌번호</td>
<td className="title" width="200">강좌이름</td>
<td className="title" width="80">강의시간</td>
<td className="title" width="80">강의실</td>
<td className="title" width="80">담당교수</td>
<td className="title" width="80">수강인원</td>
<td className="title" width="80">최대인원</td>
</tr>
{list ? list.map(item=><CourseItem key={item.lcode} course={item}/>):''}
</table>
</div>
);
};
export default CourseList;
- C:\data\react\haksa\client\src\App.js
...
import StudentList from './component/StudentList';
...
function App() {
return (
<div className="App">
<div className="menu">
...
<span><NavLink activeStyle={style} to="/courses">수강관리</NavLink></span>
</div>
...
<Route path="/courses" component={CourseList}/>
</div>
);
}
export default App;
- 교수등록 페이지를 만들고 링크를 걸어보겠다.
- C:\data\react\haksa\client\src\component\ProfessorList.js
...
import { Link } from 'react-router-dom';
const ProfessorList = () => {
...
return (
<div>
<table>
<th colSpan={6}>교수목록</th>
<tr>
<td className="title" style={{textAlign:'left'}} colSpan={6}>
<Link to="/professor/insert">교수등록</Link>
</td>
</tr>
...
</table>
</div>
);
};
export default ProfessorList;
- C:\data\react\haksa\client\src\component\(new)ProfessorInsert.js
import React from 'react';
const ProfessorInsert = () => {
return (
<div className="insert">
<h1>교수등록</h1>
<form className="frm">
<input type="text" placeholder="교수번호"/>
<input type="text" placeholder="교수이름"/>
<input type="text" placeholder="교수직함"/>
<input type="text" placeholder="담당학과"/>
<input type="text" placeholder="임용일자"/>
<input type="text" placeholder="교수급여"/>
<button type="submit">교수등록</button>
<button type="reset">등록취소</button>
</form>
</div>
);
};
export default ProfessorInsert;
- C:\data\react\haksa\client\src\App.css
.......
.insert {
width: 800px;
margin: 0px auto;
}
.frm input {
width: 100%;
height: 40px;
margin-bottom: 15px;
font-size: 25px;
}
.insert button {
background-color: blanchedalmond;
border: 1px solid burlywood;
padding: 10px 20px 10px 20px;
font-size: 20px;
border-radius: 10px 10px 10px 10px;
font-weight: bold;
color: black;
cursor: pointer;
}
- 데이터값을 input에 넣어보도록 하겠다.
- submit 작업을 해보도록 하겠다.
- DB에 데이터를 넣겠다.
- C:\data\react\haksa\client\src\component\ProfessorInsert.js
import React, { useState } from 'react';
import axios from 'axios';
const ProfessorInsert = ({history}) => {
const[form, setForm] = useState({
pcode:'601',
pname:'이방원',
dept:'한국학',
title:'정교수',
hiredate:'2021-01-01',
salary:20000000
})
const {pcode, pname, dept, title, hiredate, salary} = form;
const onChangeForm = (e) =>{
const newForm ={
...form,
[e.target.name]:e.target.value
}
setForm(newForm);
}
const onSubmit = (e) => {
e.preventDefault();
if(!window.confirm('등록하시겠습니까?')) return;
axios.post('/pro/insert',form).then((res)=>{
alert('교수등록 완료');
history.push('/professor/list');
})
}
const onReset = () => {
setForm({
pcode:'',
pname:'',
dept:'',
title:'',
hiredate:'',
salary:''
})
}
return (
<div className="insert">
<h1>교수등록</h1>
<form className="frm" onSubmit={onSubmit}>
<input type="text" name="pcode" value={pcode} onChange={onChangeForm}/>
<input type="text" name="pname" value={pname} onChange={onChangeForm}/>
<input type="text" name="title" value={title} onChange={onChangeForm}/>
<input type="text" name="dept" value={dept} onChange={onChangeForm}/>
<input type="text" name="hiredate" value={hiredate} onChange={onChangeForm}/>
<input type="text" name="salary" value={salary} onChange={onChangeForm}/>
<button type="submit">교수등록</button>
<button type="reset" onClick={onReset}>등록취소</button>
</form>
</div>
);
};
export default ProfessorInsert;
- C:\data\react\haksa\server.js
// 4. 교수 등록 메서드
app.post('/pro/insert',(req,res)=>{
var pcode = req.body.pcode;
var pname = req.body.pname;
var dept = req.body.dept;
var title = req.body.title;
var hiredate = req.body.hiredate;
var salary = parseInt(req.body.salary);
var sql = "insert into professors(pcode, pname, dept, title, hiredate, salary) values(?,?,?,?,?,?)"
con.query(sql,[pcode,pname, dept, title, hiredate, salary], (err,rows)=>{
res.send(rows);
});
});
- 교수 정보 리드 작업
- C:\data\react\haksa\client\src\App.js
import { NavLink, Route } from 'react-router-dom';
import './App.css';
import About from './component/About';
import CourseList from './component/CourseList';
import ProfessorInsert from './component/ProfessorInsert';
import ProfessorList from './component/ProfessorList';
import ProfessorRead from './component/ProfessorRead';
import StudentList from './component/StudentList';
const style={
color:'red',
fontWeight:'bold'
}
function App() {
return (
<div className="App">
<div className="menu">
<span><NavLink activeStyle={style} to="/" exact={true}>시스템소개</NavLink></span>
<span><NavLink activeStyle={style} to="/professors">교수관리</NavLink></span>
<span><NavLink activeStyle={style} to="/students">학생관리</NavLink></span>
<span><NavLink activeStyle={style} to="/courses">수강관리</NavLink></span>
</div>
<Route path="/" component={About} exact={true}/>
<Route path="/professors" component={ProfessorList}/>
<Route path="/students" component={StudentList}/>
<Route path="/courses" component={CourseList}/>
<Route path="/professor/insert" component={ProfessorInsert}/>
<Route path="/professor/read/:pcode" component={ProfessorRead}/>
</div>
);
}
export default App;
- C:\data\react\haksa\client\src\component\(new)ProfessorRead.js
import React from 'react';
const ProfessorRead = () => {
return (
<div>
</div>
);
};
export default ProfessorRead;
- C:\data\react\haksa\client\src\component\ProfessorItem.js
import React from 'react';
import { Link } from 'react-router-dom';
const ProfessorItem = ({professor}) => {
const {pcode, pname, dept, fhiredate, title, fsalary} = professor
return (
<tr>
<td><Link to={`/professor/read/${pcode}`}>{pcode}</Link></td>
<td>{pname}</td>
<td>{title}</td>
<td>{dept}</td>
<td>{fhiredate}</td>
<td>{fsalary}</td>
</tr>
);
};
export default ProfessorItem;
- C:\data\react\haksa\server.js
.....
// 5. 교수 정보 읽어오기
app.get('/pro/read/:pcode', (req,res) => {
var pcode = req.params.pcode;
var sql = "select * from professors where pcode=?";
con.query(sql,[pcode],(req,rows)=>{
// rows의 값이 하나기 때문에 [0]
res.send(rows[0]);
})
})
- C:\data\react\haksa\server.js
// 5. 교수 정보 읽어오기
app.get('/pro/read/:pcode', (req,res) => {
var pcode = req.params.pcode;
var sql = "select *,date_format(hiredate,'%Y-%m-%d') fhiredate from professors where pcode=?";
con.query(sql,[pcode],(req,rows)=>{
// rows의 값이 하나기 때문에 [0]
res.send(rows[0]);
})
})
- C:\data\react\haksa\client\src\component\ProfessorRead.js
import axios from 'axios';
import React, { useEffect, useState } from 'react';
const ProfessorRead = ({history,match}) => {
var paramsPcode = match.params.pcode;
const callAPI = async() => {
const res = await axios.get(`/pro/read/${paramsPcode}`);
setForm(res.data);
}
useEffect(()=>{
callAPI();
},[])
const[form, setForm] = useState({
pcode:'601',
pname:'이방원',
dept:'한국학',
title:'정교수',
hiredate:'2021-01-01',
salary:20000000
})
const {pcode, pname, dept, title, fhiredate, salary} = form;
const onChangeForm = (e) =>{
const newForm ={
...form,
[e.target.name]:e.target.value
}
setForm(newForm);
}
const onSubmit = (e) => {
e.preventDefault();
if(!window.confirm('수정하시겠습니까?')) return;
axios.post('/pro/insert',form);
}
const onReset = () => {
setForm({
pcode:'',
pname:'',
dept:'',
title:'',
hiredate:'',
salary:''
})
}
return (
<div className="read">
<h1>교수정보</h1>
<form className="frm" onSubmit={onSubmit}>
<input type="text" name="pcode" value={pcode} onChange={onChangeForm}/>
<input type="text" name="pname" value={pname} onChange={onChangeForm}/>
<input type="text" name="title" value={title} onChange={onChangeForm}/>
<input type="text" name="dept" value={dept} onChange={onChangeForm}/>
<input type="text" name="hiredate" value={fhiredate} onChange={onChangeForm}/>
<input type="text" name="salary" value={salary} onChange={onChangeForm}/>
<button type="submit">정보수정</button>
<button type="reset" onClick={onReset}>수정취소</button>
</form>
</div>
);
};
export default ProfessorRead;
- 수정작업을 해보겠다.
- C:\data\react\haksa\client\src\component\ProfessorRead.js
import axios from 'axios';
import React, { useEffect, useState } from 'react';
const ProfessorRead = ({history,match}) => {
var paramsPcode = match.params.pcode;
const callAPI = async() => {
const res = await axios.get(`/pro/read/${paramsPcode}`);
setForm(res.data);
}
useEffect(()=>{
callAPI();
},[])
const[form, setForm] = useState({
pcode:'601',
pname:'이방원',
dept:'한국학',
title:'정교수',
hiredate:'2021-01-01',
salary:20000000
})
const {pcode, pname, dept, title, fhiredate, salary} = form;
const onChangeForm = (e) =>{
const newForm ={
...form,
[e.target.name]:e.target.value
}
setForm(newForm);
}
const onSubmit = (e) => {
e.preventDefault();
if(!window.confirm('수정하시겠습니까?')) return;
axios.post('/pro/update',form).then((res)=>{
alert('수정완료')
history.push('/professors/list');
})
}
const onReset = () => {
callAPI();
}
return (
<div className="read">
<h1>교수정보</h1>
<form className="frm" onSubmit={onSubmit}>
<input type="text" name="pcode" value={pcode} readOnly/>
<input type="text" name="pname" value={pname} onChange={onChangeForm}/>
<input type="text" name="title" value={title} onChange={onChangeForm}/>
<input type="text" name="dept" value={dept} onChange={onChangeForm}/>
<input type="text" name="fhiredate" value={fhiredate} onChange={onChangeForm}/>
<input type="text" name="salary" value={salary} onChange={onChangeForm}/>
<button type="submit">정보수정</button>
<button>정보삭제</button>
<button type="reset" onClick={onReset}>수정취소</button>
</form>
</div>
);
};
export default ProfessorRead;
- C:\data\react\haksa\server.js
// 4. 교수 등록 메서드
app.post('/pro/update',(req,res)=>{
var pcode = req.body.pcode;
var pname = req.body.pname;
var dept = req.body.dept;
var title = req.body.title;
var hiredate = req.body.fhiredate;
var salary = parseInt(req.body.salary);
var sql = "update professors set pname=?, dept=?, title=?, salary=?, hiredate=? where pcode=?"
con.query(sql,[pname, dept, title, salary, hiredate, pcode], (err,rows)=>{
res.send(rows);
});
});
- 삭제버튼으로 데이터를 테이블에서 삭제해보도록 하겠다.
- C:\data\react\haksa\server.js
// 5. 교수 데이터 삭제 메서드
app.post('/pro/delete/:pcode',(req,res) => {
var pcode = req.params.pcode;
var sql = "delete from professors where pcode=?";
con.query(sql,[pcode],(err,rows) => {
if(err){
res.send({result:0});
}else{
res.send({result:1});
}
})
})
- C:\data\react\haksa\client\src\component\ProfessorRead.js
import axios from 'axios';
import React, { useEffect, useState } from 'react';
const ProfessorRead = ({history,match}) => {
var paramsPcode = match.params.pcode;
const callAPI = async() => {
const res = await axios.get(`/pro/read/${paramsPcode}`);
setForm(res.data);
}
useEffect(()=>{
callAPI();
},[])
const[form, setForm] = useState({
pcode:'601',
pname:'이방원',
dept:'한국학',
title:'정교수',
hiredate:'2021-01-01',
salary:20000000
})
const {pcode, pname, dept, title, fhiredate, salary} = form;
const onChangeForm = (e) =>{
const newForm ={
...form,
[e.target.name]:e.target.value
}
setForm(newForm);
}
const onSubmit = (e) => {
e.preventDefault();
if(!window.confirm('수정하시겠습니까?')) return;
axios.post('/pro/update',form).then((res)=>{
alert('수정완료')
history.push('/professors');
})
}
const onReset = () => {
callAPI();
}
const onDelete = (e) => {
e.preventDefault();
if(!window.confirm(`${paramsPcode} 을(를) 삭제하시겠습니까?`)) return;
axios.post(`/pro/delete/${paramsPcode}`,paramsPcode).then((res)=>{
if(res.data.result===1){
alert('삭제완료')
}else{
alert('삭제실패')
}
history.push('/professors')
})
}
return (
<div className="read">
<h1>교수정보</h1>
<form className="frm" onSubmit={onSubmit}>
<input type="text" name="pcode" value={pcode} readOnly/>
<input type="text" name="pname" value={pname} onChange={onChangeForm}/>
<input type="text" name="title" value={title} onChange={onChangeForm}/>
<input type="text" name="dept" value={dept} onChange={onChangeForm}/>
<input type="text" name="fhiredate" value={fhiredate} onChange={onChangeForm}/>
<input type="text" name="salary" value={salary} onChange={onChangeForm}/>
<button type="submit">정보수정</button>
<button type="button" onClick={onDelete}>정보삭제</button>
<button type="reset" onClick={onReset}>수정취소</button>
</form>
</div>
);
};
export default ProfessorRead;
- 신규 프로젝트로 블로그 작업을 해보겠다.
-교재 p91
// 신규 프로젝트 생성
yarn create react-app blog
- Mysql에서 신규 DB를 생성하도록 하겠다.
#2021.09.16
create user 'blog'@'localhost' identified by 'pass';
create database blogDB;
grant all privileges on blogDB.* to 'blog'@'localhost';
- 유저 테이블 생성, 데이터 입력, 확인
create table tbl_user(
userid varchar(20) not null primary key,
username varchar(20),
password varchar(100) not null
);
insert into tbl_user values('red', '홍길동', 'pass');
insert into tbl_user values('blue', '강감찬', 'pass');
insert into tbl_user values('yellow', '심청이', 'pass');
select * from tbl_user;
- 포스트(글) 테이블 생성, 데이터 입력, 확인
create table tbl_post(
id int auto_increment primary key,
userid varchar(20) not null,
title varchar(500) not null,
body varchar(1000),
createDate datetime default now(),
foreign key(userid) references tbl_user(userid)
);
insert into tbl_post(userid, title, body)
values('red','왜 리액트인가?','한때 자바스크립트는 웹 브라우저에서 간단한 연산을 했지만 현재는 웹 애플리케이션에서 가장 핵심적인 역할을 한다.');
insert into tbl_post(userid, title, body)
values('blue','컴포넌트','컴포넌트를 선언하는 방식은 두 가지이다. 하나는 함수형 컴포넌트이고, 또 다른 하나는 클래스형 컴포넌트이다');
insert into tbl_post(userid, title, body)
values('yellow','배열 비구조화 할당','배열 안에 들어 있는 값을 쉽게 추출할 수 있도록 해 주는 문법이다.');
select * from tbl_post;
- VSC - 클라이언트 서버, DEV 서버 작업
- C:\data\react\blog\(new)package.json
{
"name": "management",
"version": "1.0.0",
"private": true,
"scripts": {
"client": "cd client && yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
}
}
- C:\data\react\blog\(new)server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
app.use(express.json());
app.get('/', (req, res) => {
res.send({
success: true
})
});
app.listen(port, () => {
console.log(`server is listening at localhost:${port}`);
});
- 폴더에서 웹서버를 구축하기 위한 express와 서버와 클라이언트를 동시에 실행하기 위한 concurrently를 아래와 같이 설치한다. 폴더에서 웹서버 구동을 위한 nodemon을 설치하면 [blog]-[node_modules] 폴더가 생성된다.
- VSC\Terminal
// 프로젝트 폴더로 이동
C:\data\react>cd blog
// nodemon 설치
C:\data\react\blog>npm install nodemon
// express 라이브러리 설치
C:\data\react\blog>npm install express concurrently
// mysql 설치
C:\data\react\blog>yarn add mysql
- C:\data\react\blog\package.json
{
"name": "management",
"version": "1.0.0",
"private": true,
"scripts": {
"client": "cd client && yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
},
"dependencies": {
"concurrently": "^6.2.1",
"express": "^4.17.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.12",
}
}
- 클라이언트 서버 작업
// 엑시오스 라이브러리 설치
yarn add axios
// 리액트 라우터 라이브러리 설치
yarn add react-router-dom
- C:\data\react\blog\client\package.json
{
"name": "blog",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"axios": "^0.21.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.3.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
- 서버 구동
C:\data\react\blog>yarn dev
- 종합
// 프로젝트 생성
react\yarn create react-app 프로젝트명
// 클라이언트 웹서버 구동을 위한 nodemon
프로젝트명\npm install nodemon
// 개발자 웹서버 구축을 위한 express, 클라이언트와 동시 실행을 위한 concurrently 설치
프로젝트명\npm install express concurrently
// DB 이용을 위한 mysql 라이브러리 설치
프로젝트명\yarn add mysql
// 클라이언트 폴더에서 리엑트 라우터 라이브러리 설치
프로젝트명\client\yarn add react-router-dom
// 클라이언트 폴더에서 axios 라이브러리 설치
프로젝트명\client\yarn add axois
- 서버에 mysql을 이용해 특정 DB에 연결하는 작업을 하도록 하겠다.
- C:\data\react\blog\server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
// DB 연결
const mysql = require('mysql');
exports.con = mysql.createConnection({
host: "localhost",
user: "haksa",
password: "pass",
port: "3306",
database: "haksadb"
});
app.use(express.json());
app.get('/', (req, res) => {
res.send({
success: true
})
});
app.listen(port, () => {
console.log(`server is listening at localhost:${port}`);
});
- 라우터를 따로 분리해서 생성하도록 하겠다.
- C:\data\react\blog\(new)routes
- C:\data\react\blog\routes\(new)posts.js
const express = require('express');
const router = express.Router();
const db = require('../server');
module.exports = router;
- C:\data\react\blog\routes\(new)auth.js
const express = require('express');
const router = express.Router();
const db = require('../server');
module.exports = router;
- C:\data\react\blog\server.js
....
app.use('/post',require('./routes/posts'));
app.use('/auth',require('./routes/auth'));
- 비밀번호 아이디 체크 라우터를 생성하도록 하겠다.
- C:\data\react\blog\routes\auth.js
const express = require('express');
const router = express.Router();
const db = require('../server');
//아이디체크
router.get('/:userid', (req, res)=>{
var userid = req.params.userid;
var sql = 'select * from tbl_user where userid=?';
db.con.query(sql,[userid],(err, rows)=>{
res.send(rows);
});
})
module.exports = router;
- C:\data\react\blog\routes\posts.js
const express = require('express');
const router = express.Router();
const db = require('../server');
//게시글목록
router.get('/', (req, res) => {
var sql = 'select * from tbl_post';
db.con.query(sql, (err, rows) => {
res.send(rows);
})
})
module.exports = router;
- C:\data\react\blog\client\src\index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
// 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();
- C:\data\react\blog\client\src\App.js
import './App.css';
import { Route } from 'react-router-dom'
import LoginPage from './pages/LoginPage';
function App() {
return (
<div className="App">
<Route path="/login" component={LoginPage}/>
</div>
);
}
export default App;
- C:\data\react\blog\client\src\(new)pages
- C:\data\react\blog\client\src\pages\(new)LoginPage.js
import React from 'react';
import Auth from '../components/Auth';
const LoginPage = () => {
return (
<div>
<Auth/>
</div>
);
};
export default LoginPage;
- C:\data\react\blog\client\src\(new)components
- C:\data\react\blog\client\src\components\(new)Auth.js
import React from 'react';
import { Link } from 'react-router-dom';
import '../css/Auth.css'
const Auth = () => {
return (
<div className="authBlock">
<div className="whiteBox">
<div className="logo-area">
<Link to="/">REACTERS</Link>
</div>
<div className="authForm">
<h3>로그인</h3>
<form>
<input type="text" placeholder="ID"/>
<input type="password" placeholder="PW"/>
<button type="submit">로그인</button>
</form>
<div className="footer">
<Link to='/register'>회원가입</Link>
</div>
</div>
</div>
</div>
);
};
export default Auth;
- C:\data\react\blog\client\src\(new)css
- C:\data\react\blog\client\src\css\(new)Auth.css
.authBlock {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #e2e2e2;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.logo-area {
font-size: 1.4rem;
padding-bottom: 2rem;
text-align: center;
font-weight: bold;
letter-spacing: 2px;
}
.whiteBox {
width: 360px;
box-shadow: 5px 5px 5px gray;
border-radius: 10px;
padding: 2rem;
background: white;
}
.authForm input {
width: 100%;
font-size: 1rem;
border: none;
padding-bottom: 0.5rem;
outline: none;
border-bottom: 1px solid #e2e2e2;
margin-top: 1rem;
}
.authForm input:focus {
border-bottom: 1px solid #495057;
}
.authForm button {
width: 100%;
border: none;
border-radius: 4px;
font-size: 1rem;
font-weight: bold;
background: #22b8cf;
color: white;
margin-top: 1rem;
padding-top: 0.7rem;
padding-bottom: 0.7rem;
cursor: pointer;
}
.authForm button:hover {
background: #3bc9db;
}
.footer {
margin-top: 2rem;
text-align: right;
}
.footer a {
text-decoration: underline;
color: gray;
}
.footer a:hover {
color: #bebebe;
}
.errorMessage {
color: red;
text-align: center;
font-size: 0.875rem;
margin-top: 1rem;
}
- 아이디가 tbl_user에 있는지 확인해주도록 하겠다.
- C:\data\react\blog\client\src\components\Auth.js
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import '../css/Auth.css';
import axios from 'axios';
const Auth = () => {
// 메시지 관리 스테이트 변수
const [ error,setError] = useState('');
// 데이터 입력 스테이트 변수
const [form,setForm] = useState({
userid:'red',
password:'pass',
username:''
});
const {userid, password} = form;
const onChangeForm = (e) => {
setForm({
...form,
[e.target.name]:e.target.value
})
}
const onSubmit = (e) =>{
setError('');
e.preventDefault();
if(userid==='' || password===''){
setError('빈 칸을 모두 입력하세요.');
return;
}
axios.get(`/auth/${userid}`)
.then(res => {
if(res.data.length===1){
if(res.data[0].password === password){
setError('로그인성공');
}else{
setError('비밀번호가 일치하지 않습니다.')
}
}else{
setError('해당 아이디가 존재하지 않습니다.')
}
});
}
return (
<div className="authBlock">
<div className="whiteBox">
<div className="logo-area">
<Link to="/">REACTERS</Link>
</div>
<div className="authForm">
<h3>로그인</h3>
<form onSubmit={onSubmit}>
<input type="text" placeholder="ID" name="userid" value={userid} onChange={onChangeForm}/>
<input type="password" placeholder="PW" name="password" value={password} onChange={onChangeForm}/>
<button type="submit">로그인</button>
</form>
{/* error가 있으면(&&) */}
{error && <div className="errorMessage">{error}</div>}
<div className="footer">
<Link to='/register'>회원가입</Link>
</div>
</div>
</div>
</div>
);
};
export default Auth;
- C:\data\react\blog\client\package.json
{
....
},
"proxy": "http://localhost:5000/"
}
- 회원가입
- C:\data\react\blog\client\src\components\(new)Register.js
import React from 'react';
import { Link } from 'react-router-dom';
import '../css/Auth.css'
const Register = () => {
return (
<div className="authBlock">
<div className="whiteBox">
<div className="logo-area">
<Link to="/">REACTERS</Link>
</div>
<div className="authForm">
<h3>회원가입</h3>
<form>
<input type="text" placeholder="ID" name="userid"/>
<input type="password" placeholder="PW" name="password"/>
<input type="password" placeholder="PW Check" name="passwordConfirm"/>
<button type="submit">회원가입</button>
</form>
<div className="footer">
<Link to='/login'>로그인</Link>
</div>
</div>
</div>
</div>
);
};
export default Register;
- C:\data\react\blog\client\src\pages\(new)RegisterPage.js
import React from 'react';
import Register from '../components/Register';
const RegisterPage = () => {
return (
<div>
<Register/>
</div>
);
};
export default RegisterPage;
- C:\data\react\blog\client\src\App.js
import './App.css';
import { Route } from 'react-router-dom'
import LoginPage from './pages/LoginPage';
import RegisterPage from './pages/RegisterPage';
function App() {
return (
<div className="App">
<Route path="/login" component={LoginPage}/>
<Route path="/register" component={RegisterPage}/>
</div>
);
}
export default App;
- 이제 회원가입하여 DB에 데이터를 넣도록 하겠다.
- C:\data\react\blog\client\src\components\Register.js
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import '../css/Auth.css'
const Register = () => {
const [error,setError] = useState('');
const [form,setForm] = useState({
userid:'black',
password:'pass',
passwordConfirm:'pass'
});
const { userid, password, passwordConfirm } = form;
const onChnageForm = (e) => {
setForm({
...form,
[e.target.name]:e.target.value
})
}
const onSubmit = (e) => {
e.preventDefault();
setError('');
if(userid==='' || password==='' || passwordConfirm===''){
setError('빈칸을 모두 입력하세요.');
return;
}
if(password != passwordConfirm){
setError('비밀번호를 확인하세요.')
return;
}
if(!window.confirm('가입하시겠습니까?')) return;
}
return (
<div className="authBlock">
<div className="whiteBox">
<div className="logo-area">
<Link to="/">REACTERS</Link>
</div>
<div className="authForm">
<h3>회원가입</h3>
<form onSubmit={onSubmit}>
<input type="text" placeholder="ID" name="userid" value={userid} onChange={onChnageForm}/>
<input type="password" placeholder="PW" name="password" value={password} onChange={onChnageForm}/>
<input type="password" placeholder="PW Check" name="passwordConfirm" value={passwordConfirm} onChange={onChnageForm}/>
<button type="submit">회원가입</button>
</form>
{/* error가 있으면(&&) */}
{error && <div className="errorMessage">{error}</div>}
<div className="footer">
<Link to='/login'>로그인</Link>
</div>
</div>
</div>
</div>
);
};
export default Register;
- C:\data\react\blog\routes\auth.js
.....
// 2. 회원가입
router.post('/register', (req,res) => {
var userid = req.body.userid;
var password = req.body.password;
var sql = "insert into tbl_user(userid, password) values(?,?)";
db.con.query(sql,[userid,password],(err,rows) => {
if(err){
res.send({result:false});
}else{
res.send({result:true});
}
})
})
....
- C:\data\react\blog\client\src\components\Register.js
import React, { useState } from 'react';
import { Link, useHistory } from 'react-router-dom';
import '../css/Auth.css'
import axios from 'axios';
const Register = ({history}) => {
const [error,setError] = useState('');
const [form,setForm] = useState({
userid:'black',
username:'이주성',
password:'pass',
passwordConfirm:'pass'
});
const { userid, username , password, passwordConfirm } = form;
const onChnageForm = (e) => {
setForm({
...form,
[e.target.name]:e.target.value
})
}
var history = useHistory();
const onSubmit = (e) => {
e.preventDefault();
setError('');
if(userid==='' || username==='' || password==='' || passwordConfirm===''){
setError('빈칸을 모두 입력하세요.');
return;
}
if(password != passwordConfirm){
setError('비밀번호를 확인하세요.')
return;
}
if(!window.confirm('가입하시겠습니까?')) return;
axios.post('/auth/register', form).then(res=>{
if(res.data.result){
setError('가입되었습니다.')
history.push('/login')
}else{
setError('이미 존재하는 계정입니다.')
}
});
}
return (
<div className="authBlock">
<div className="whiteBox">
<div className="logo-area">
<Link to="/">REACTERS</Link>
</div>
<div className="authForm">
<h3>회원가입</h3>
<form onSubmit={onSubmit}>
<input type="text" placeholder="ID" name="userid" value={userid} onChange={onChnageForm}/>
<input type="text" placeholder="Name" name="username" value={username} onChange={onChnageForm}/>
<input type="password" placeholder="PW" name="password" value={password} onChange={onChnageForm}/>
<input type="password" placeholder="PW Check" name="passwordConfirm" value={passwordConfirm} onChange={onChnageForm}/>
<button type="submit">회원가입</button>
</form>
{/* error가 있으면(&&) */}
{error && <div className="errorMessage">{error}</div>}
<div className="footer">
<Link to='/login'>로그인</Link>
</div>
</div>
</div>
</div>
);
};
export default Register;
Uncaught TypeError: Cannot read property 'push' of undefined (React-Router-Dom)
I have a Dashboard with rotating slides, each of which has a corresponding tab in Bldgs. Both Dashboard.js and Bldgs.js are children to my App.js. When a user clicks on a specific slide A in Dashb...
stackoverflow.com
'ICIA 수업일지' 카테고리의 다른 글
2021.09.23 수업일지(안드로이드 개발 기초, Activity, View) (0) | 2021.09.23 |
---|---|
2021.09.17 수업일지(React.js을 이용한 블로그 개설) (0) | 2021.09.17 |
2021.09.15 수업일지(React.js) (0) | 2021.09.15 |
2021.09.14 수업일지(React.js) (0) | 2021.09.14 |
2021.09.13 수업일지(React.js) (0) | 2021.09.13 |