본문 바로가기
ICIA 수업일지

2021.09.16 수업일지(React.js)

by 주성씨 2021. 9. 16.

- 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;

 

확인 (외래키로 이용되어 있는 컬럼은 cascade하지 않는 이상 삭제가 안된다)

 

 

- 신규 프로젝트로 블로그 작업을 해보겠다.

-교재 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;

 

https://stackoverflow.com/questions/44009618/uncaught-typeerror-cannot-read-property-push-of-undefined-react-router-dom

 

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

 

확인

 

확인