일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Recoil
- Typescript
- Outlet
- 프로그래머스
- programmers
- 오블완
- 42747
- 티스토리챌린지
- Helmet
- 138476
- userecoilvalue
- usesetrecoilstate
- React
- 노마드코더
- 귤 고르기
- H-index
- useoutletcontext
- Today
- Total
오늘도 코딩하나
[React] nodejs + mysql 연동 (2) Router, Redux-toolkit 사용하는 경우 본문
기본적인 mysql 연동에 대한 내용은 하단 내용을 참고하길 바란다.
https://coding-hana.tistory.com/49
[React] nodejs + mysql 연동
(1) server 세팅npm init -ynpm install expressnpm install nodemonnpm install cors - server.jsconst express = require('express');const db = require('/database/db');const app = express();const path = require('path')const port = 8009;app.listen(port, functi
coding-hana.tistory.com
1. 서버 설정
- server.js
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, '../account/build', 'index.html'));
})
(React) index.html - 여러 페이지 렌더링
→ 모든 경로에 대해 index.html 반환하도록 설정하여, React Router가 클라이언트 측에서 라우팅 관리
(Server) 기본적으로 정적 파일만 서빙하고,
'GET /about', 'GET /contact'와 같은 요청에 대해 서버에서 해당 경로를 처리하지 않기 때문에 404 오류 반환
* API 경로가 해당 소스보다 상위에 있어야 한다.
2. Redux-tookit 설정
- dataSlice.js
import { configureStore, createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from 'axios';
// MySQL에서 데이터 가져오기
export const fetchData = createAsyncThunk('list/fetchData', async () => {
const response = await axios.get('http://localhost:8009/list');
return response.data;
});
// MySQL에서 데이터 저장하기
export const saveData = createAsyncThunk('list/insert', async (data) => {
const response = await axios.post('http://localhost:8009/list/insert', data);
return response.data;
});
let listData = createSlice({
name: 'listData',
initialState : {
items : [],
status: 'idle',
error: null,
},
extraReducers: (builder) => {
builder
.addCase(fetchData.pending, (state) => {
state.status = 'loading'
})
.addCase(fetchData.fulfilled, (state, action) => {
state.status = 'succeeded';
state.items = action.payload;
})
.addCase(fetchData.rejected, (state, action) => {
state.status = 'failed'
state.items = action.error.message;
})
.addCase(saveData.fulfilled, (state, action) => {
state.items = action.payload
})
}
})
export default configureStore({
reducer: {
listData : listData.reducer
}
})
▷ status : idle(요청이 시작되지 않음) / loading(요청이 진행 중) / succeeded(요청 성공) / failed(요청 실패)
- App.js
const listData = useSelector((state) => state.listData.items);
const payListStatus = useSelector((state) => state.listData.status);
useEffect(() => {
if(payListStatus === 'idle') {
dispatch(fetchData());
}
}, [payListStatus, dispatch]);
const addData = () => {
dispatch(saveData({name, age}));
}
return (
<div className="App">
<h1>React MySQL 연동</h1>
{payListStatus === 'loading' && <div>Loading...</div>}
{payListStatus === 'succeeded' && (
<ul>
{Array.isArray(data) && data.map(item => (
<li key={item.id}>{item.name} - {item.age}</li>
))}
</ul>
)}
{payListStatus === 'failed' && (
<div>Fail!</div>
)}
<input type="text" placeholder="이름을 입력하세요." value={name} onChange={e => setName(e.target.value)} />
<input type="text" placeholder="나이를 입력하세요." value={age} onChange={e => setAge(e.target.value)} />
<button onClick={addData}>Add Data</button>
</div>
)
▶ createAsyncThunk & extraReducer
Redux toolkit에서 비동기 작업을 보다 쉽게 처리하고 상태를 관리할 수 있도록 제공하는 기능
- createAsyncThunk : 비동기 처리를 할 액션 정의
- extraReducer : 비동기 액션의 결과를 처리하여 상태 변경 로직 정의
* extraReducer vs reducer
- reducers : 동기적 / action creator을 자동으로 toolkit이 만들어줌
- extraReducers : 비동기적 / action creator을 자동으로 만들지 못함
→ slice의 extraReducers에 직접 action creator 정의
'React > 코딩애플' 카테고리의 다른 글
[React] nodejs + mysql 연동 (1) (0) | 2024.09.04 |
---|---|
[React] (8) props 전송 없이 state 공유하기 (0) | 2024.07.09 |
[React] (7) 서버 통신 (0) | 2024.06.07 |
[React] (6) Lifecycle과 useEffect (1) | 2024.06.04 |
[React] (5) 리액트 라우터 (0) | 2024.05.28 |