2024. 5. 12. 17:22ㆍ· FRONT-END/└ React
환경 : Visual Studio Code, Spring Tool Suite4
백엔드 코드 이해 설명 링크 : https://ggingggang05.tistory.com/228

리액트에서 비동기 처리를 위해서 ajax를 사용할 수 있다. 하지만 이는 jquery를 사용했을 경우만 가능하다. 따라서 axios를 활용하여 비동기 통신을 구현할 수 있다.
1) 원하는 프로젝트에 설치한다.
npm install axios
비동기를 사용할 js에 비동기 통신 전용 라이브러리를 import 해준다
import axios from "axios"; //비동기 통신 전용 라이브러리
(참고) 이후 비동기 통신 진행시 콘솔에서 확인 가능

2) index.js 파일에 <React.StrictMode> 태그를 제거해준다
<React.StrictMode>가 있으면 리액트가 화면을 두 번씩 실행하기 때문에 제거해주는 것이 좋다. (한 번은 테스트)
또한, 통신 등에서 문제가 될 수 있으므로 사용하지 않는 것을 권장한다
- index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
//bootstrap
import "bootstrap/dist/css/bootstrap.min.css";
import "bootswatch/dist/cosmo/bootstrap.min.css";
import './index.css';
import "bootstrap"; //js는 경로를 생략해도 기본 경로로 설정됨
import { HashRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
//<React.StrictMode>가 있으면 리액트가 화면을 두 번씩 실행한다.(한 번은 테스트)
//통신 등에서 문제가 될 수 있으므로 사용하지 않는 것을 권장
root.render(
<>
{/* 리액트 라우터를 사용하는 영역을 지정 */}
<HashRouter>
<App />
</HashRouter>
</>
);
// 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();
3) 코드 작성
//목록
useEffect(() => {
loadData();
}, []);
const loadData = useCallback(() => {
axios.get("http://localhost:8080/emp/").then(resp => {
setEmps(resp.data);
});
}, [emps]);
(+) loadData 함수를 만들어 여러 곳에서 재활용하도록 만들었다.
(+) effect란?
(+) $.ajax와 axios 비교
const saveInput = useCallback((e) => {
axios({
url: "http://localhost:8080/emp/",
method: "post",
data: input
}).then(resp => {
loadData();
setInput({
empName: "",
empDept: "",
empDate: "",
empSal: ""
});
closeModal();
});
}, [input]);
(+) 데이터는 input에 있는 내용을 넘겨주면 된다!
//ref
const bsModal = useRef();
const openModal = useCallback(() => {
const modal = new Modal(bsModal.current)
modal.show();
}, [bsModal]);
const closeModal = useCallback(() => {
const modal = Modal.getInstance(bsModal.current);
modal.hide();
}, [bsModal]);
(+) ref(참조)
- 리액트에서 태그를 선택하는 대신 사용하는 도구로 그 외의 용도도 가능하다
- 변수명.current를 이용하여 현재 참조하고 있는 대상 태그를 호출할 수 있다
- emp.js 전체코드
import Jumbotron from "../Jumbotron";
import { useCallback, useEffect, useRef, useState } from "react";
import axios from "axios"; //비동기 통신 전용 라이브러리
import { Modal } from "bootstrap";
import { FaPlus } from "react-icons/fa";
import { HiArchiveBoxXMark } from "react-icons/hi2";
function Emp() {
//state
const [emps, setEmps] = useState([]);
const [input, setInput] = useState({
empName: "",
empDept: "",
empDate: "",
empSal: ""
});
//목록 불러오기
const loadData = useCallback(() => {
axios.get("http://localhost:8080/emp/").then(resp => {
setEmps(resp.data);
});
}, [emps]);
//목록
useEffect(() => {
loadData();
}, []);
//회원 등록
const changeInput = useCallback((e) => {
setInput({
...input, //원래 회원은 유지하며
[e.target.name]: e.target.value //name에 해당하는 값만 value로 바꿔 추가!
});
}, [input]);
const saveInput = useCallback((e) => {
axios({
url: "http://localhost:8080/emp/",
method: "post",
data: input
}).then(resp => {
//등록이 완료되면 갱신을 진행
loadData();
setInput({ //화면 비우기
//empNo의 경우 시퀀스로 받기 때문에 사용자에게 입력받지 않아도 됨
empName: "",
empDept: "",
empDate: "",
empSal: ""
});
closeModal();
});
}, [input]);
const cancelInput = useCallback((e) => {
const choice = window.confirm("정말 취소하시겠습니까?");
if (choice === false) return;
setInput({
empName: "",
empDept: "",
empDate: "",
empSal: ""
});
closeModal();
});
//회원삭제
const deleteEmp = useCallback((target) => {
const choice = window.confirm("정말 삭제하시겠습니까?");
if (choice === false) return;
//삭제 비동기 요청 후 목록 갱신
axios({
url: "http://localhost:8080/emp/" + target.empNo,
// url:`http://localhost:8080/emp/${target.empNo}`, //백틱 구문
method: "delete",
}).then(resp => {
loadData();
});
}, [emps]);
//ref
const bsModal = useRef();
const openModal = useCallback(() => {
const modal = new Modal(bsModal.current)
modal.show();
}, [bsModal]);
const closeModal = useCallback(() => {
const modal = Modal.getInstance(bsModal.current);
modal.hide();
}, [bsModal]);
return (
<>
<Jumbotron title="사원관리" />
{/* 신규등록버튼 */}
<div className="row mt-4">
<div className="col text-end">
<button className="btn btn-primary" onClick={e=>openModal()}>
<FaPlus />신규등록
</button>
</div>
</div>
{/* 목록 출력 */}
<div className="row mt-4">
<div className="col text-center">
<table className="table table-hover">
<thead>
<tr>
<th>사원번호</th>
<th>사원명</th>
<th>부서명</th>
<th>입사일</th>
<th>급여액</th>
<th>관리</th>
</tr>
</thead>
<tbody>
{emps.map(emp => (
<tr key={emp.empNo}>
<td>{emp.empNo}</td>
<td>{emp.empName}</td>
<td>{emp.empDept}</td>
<td>{emp.empDate}</td>
<td>{emp.empSal}</td>
<td>
<button className="btn btn-danger"
onClick={e => deleteEmp(emp)}>
<HiArchiveBoxXMark />삭제
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* 등록 */}
<div ref={bsModal} class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="staticBackdropLabel">사원 등록</h1>
<button type="button" class="btn-close" aria-label="Close" onClick={e=>cancelInput()}></button>
</div>
<div class="modal-body">
<div className="row mt-4">
<div className="col">
<label>사원명</label>
<input type="text" name="empName" value={input.empName}
onChange={e => changeInput(e)} className="form-control"></input>
</div>
</div>
<div className="row mt-4">
<div className="col">
<label>부서명</label>
<input type="text" name="empDept" value={input.empDept}
onChange={e => changeInput(e)} className="form-control"></input>
</div>
</div>
<div className="row mt-4">
<div className="col">
<label>입사일</label>
<input type="text" name="empDate" value={input.empDate}
onChange={e => changeInput(e)} className="form-control"></input>
</div>
</div>
<div className="row mt-4">
<div className="col">
<label>급여액</label>
<input type="text" name="empSal" value={input.empSal}
onChange={e => changeInput(e)} className="form-control"></input>
</div>
</div>
</div>
<div class="modal-footer">
<button className="btn btn-success me-2" onClick={e => saveInput()}>등록</button>
<button className="btn btn-danger" onClick={e => cancelInput()}>취소</button>
</div>
</div>
</div>
</div>
</>
);
}
export default Emp;
4) 코드 실행
- 출력결과


개인 공부 기록용입니다:)
'· FRONT-END > └ React' 카테고리의 다른 글
[ JavaScript / React ] recoil 사용 - 외부 상태 저장소 만들기 (0) | 2024.05.13 |
---|---|
[ JavaScript / React ] 비동기 통신.. 개조.. 그리고 CRUD....... (0) | 2024.05.12 |
[ React ] 아.추하기 (아이콘 추가하기라는 뜻) (0) | 2024.05.11 |
[ JavaScript / React ] 등록/조회/삭제 해보기 (0) | 2024.05.09 |
[ JavaScript / React ] 삭제 효과 내보기 (0) | 2024.05.08 |