รายละเอียดสำหรับเรียนรู้ React ปี 2020-2023 โดยโค้ชพล ดูหลักสูตรได้ที่ https://www.nextflow.in.th/react-training
npm i axios
หรือ
yarn add axios
สร้างไฟล์ src/redux/action.js
import axios from "axios";
//..
const axiosClient = axios.create({
responseType: "json"
});
// src/App.js
//..
useEffect(() => {
const requestInitData = async (dispatch) => {
try {
// ใช้ Axios เข้าถึงข้อมูล JSON แทน
const success = await axiosClient.get('https://www.nextflow.in.th/api/branch-info/branch.json');
console.log(success.data);
} catch (error) {
console.error(error);
}
}
requestInitData()
})
// src/redux/action.js
export default {
SHOW_BRANCH_DATA: "SHOW_BRANCH_DATA",
REQUEST_INIT_DATA: "REQUEST_INIT_DATA",
// ในกรณีที่ได้ข้อมูลมาอย่างไม่มีปัญหา
REQUEST_INIT_DATA_SUCCESS: "REQUEST_INIT_DATA_SUCCESS",
// ในกรณีที่มีการผิดพลาดในการเรียกข้อมูล
REQUEST_INIT_DATA_FAILED: "REQUEST_INIT_DATA_FAILED",
}
จากจุดนี้ให้ทำการ dispatch action type ที่เหมาะสมจาก App component
// src/App.js
const requestInitData = () => {
return async (dispatch) => {
try {
const success = await API.get('./branch.json');
console.log(success.data);
// dispatch action พร้อมข้อมูลที่ได้เข้า Redux store
dispatch({
type: ActionTypes.REQUEST_INIT_DATA_SUCCESS,
payload: success.data
})
} catch (error) {
// dispatch action พร้อม error ทีไ่ด้เข้า redux store
dispatch({
type: ActionTypes.REQUEST_INIT_DATA_FAILED,
payload: error
})
}
}
}
เปิดไฟล์ src/redux/reducer.js
เริ่มจากกำหนดค่า initialState.app
เพื่อใช้อ้างอิงใน App Component ว่าต้องแสดง notification หรือไม่
const initialState = {
branches: BranchModel.branches,
branchDataInChart: {
chartField: ['Month','Amount'],
datas: [
{ month: '', amount: 0 }
]
},
app: {
}
}
ถ้าไม่ต้องแสดงตัวแจ้งเตือน ให้กำหนด initialState.app.notification
เป็น {}
แต่ถ้าเป็น Action ผลลัพธ์จากการโหลดข้อมูล (ทั้งสำเร็จ และไม่สำเร็จ) จะมีการกำหนดค่าให้ app.notification
case Action.REQUEST_INIT_DATA_SUCCESS: {
return {
...state,
// กำหนดข้อมูลที่จะใช้ในกลไกสร้าง notification
app: {
notification: {
message: 'Data Loaded',
isError: false,
isShow: true
}
}
}
}
case Action.REQUEST_INIT_DATA_FAILED: {
return {
...state,
// กำหนดข้อมูล error ที่จะใช้ในกลไกสร้าง notification
app: {
notification: {
message: payload.message,
isError: true,
isShow: true
}
}
}
}
import branchModel from "../models/branchModel"
import Action from './action'
const initialState = {
branches: branchModel.branches,
branchDataInChart: {
chartField: ['Month','Amount'],
datas: [
{ month: '', amount: 0 }
]
},
app: {
}
}
export default (state = initialState, { type, payload }) => {
switch (type) {
case Action.SHOW_BRANCH_DATA: {
console.log(`branchId: ${payload}`)
let selectingBranch = state.branches.find(branch => {
return branch.id === payload;
})
if (selectingBranch) {
return {
...state,
branchDataInChart: { ...selectingBranch.chartData }
}
} else {
return { ...state }
}
}
case Action.REQUEST_INIT_DATA_SUCCESS: {
return {
...state,
app: {
notification: {
message: 'Data Loaded',
isError: false,
isShow: true
}
}
}
}
case Action.REQUEST_INIT_DATA_FAILED: {
return {
...state,
app: {
notification: {
message: payload.message,
isError: true,
isShow: true
}
}
}
}
default:
return state
}
}
เปิดไฟล์ src/App.js
แล้ว import message
ของ Ant Design เข้ามา
import { Layout, Row, Col, message } from 'antd';
จากนั้น เรียกใช้ค่า state.app.notification
ผ่าน React hook ที่ชื่อ useSelector()
import { useDispatch, useSelector } from 'react-redux'
//..
const notification = useSelector(state => state.app.notification)
จากนั้นเรียกใช้ React hook useEffect
สำหรับค่า notification โดยเฉพาะ
const notification = useSelector(state => state.app.notification)
useEffect(() => {
// เช็คข้อมูล notification เพื่อแจ้งเตือน
if (notification && notification.isShow) {
if (notification.isError) {
message.error(notification.message);
} else {
message.success(notification.message);
}
}
// รัน use effect อีกครั้งถ้ามีการเปลี่ยนแปลงค่าของ notification
}, [notification])
//import logo from './logo.svg';
import './App.css';
import HeaderBar from './components/HeaderBar';
import { Layout, Row, Col, message } from 'antd';
import MapBranch from './components/MapBranch';
import StatChart from './components/StatChart';
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import Action from './redux/action'
import axios from "axios";
const axiosClient = axios.create({
responseType: "json"
});
const { Content, Footer } = Layout;
function App() {
const dispatch = useDispatch();
useEffect(() => {
const requestInitData = async (dispatch) => {
try {
const success = await axiosClient.get('./branch.json');
console.log(success.data);
dispatch({ type: Action.REQUEST_INIT_DATA_SUCCESS, payload: success.data })
} catch (error) {
console.error(error);
dispatch({ type: Action.REQUEST_INIT_DATA_FAILED, payload: error })
}
}
requestInitData(dispatch)
}, [])
const notification = useSelector(state => state.app.notification)
useEffect(() => {
if (notification && notification.isShow) {
if (notification.isError) {
message.error(notification.message);
} else {
message.success(notification.message);
}
}
}, [notification])
return (
<div>
<Layout className="layout">
<HeaderBar />
<Content style=>
<div
style=>
<Row gutter={16}>
<Col span={12}><MapBranch /></Col>
<Col span={12}><StatChart /></Col>
</Row>
</div>
</Content>
<Footer style=>React Redux Workshop ©2012-2020 Created by Nextflow.in.th</Footer>
</Layout>,
</div>
);
}
export default App;
เปิดไฟล์ src/redux/reducer.js
ก่อนอื่น เรากำหนดค่า initialState.branches
เป็น []
const initialState = {
branches: [],
branchDataInChart: {
chartField: ['Month','Amount'],
datas: [
{ month: '', amount: 0 }
]
}
}
จากนั้น ในกรณีที่การโหลด JSON สมบูรณ์ ให้ส่ง payload ที่ได้ออกไปให้ Component
case Actions.ActionTypes.REQUEST_INIT_DATA_SUCCESS: {
return {
...state,
branches: payload.branches,
app: {
notification: {
message: 'Data Loaded',
isError: false,
isShow: true
}
}
}
}
import Actions from "./actions";
import BranchModel from "../models/branchModel";
const initialState = {
branches: [],
branchDataInChart: {
chartField: ['Month','Amount'],
datas: [
{ month: '', amount: 0 }
]
},
app: {
}
}
export default (state = initialState, { type, payload }) => {
switch (type) {
case Actions.ActionTypes.SHOW_BRANCH_DATA: {
console.log(`branchId: ${payload}`)
let selectingBranch = this.branches.find(branch => {
return branch.id === payload;
})
if (selectingBranch) {
return {
...state,
branchDataInChart: { ...selectingBranch.chartData }
}
} else {
return { ...state }
}
}
case Actions.ActionTypes.REQUEST_INIT_DATA_SUCCESS: {
return {
...state,
branches: payload.branches,
app: {
notification: {
message: 'Data Loaded',
isError: false,
isShow: true
}
}
}
}
case Actions.ActionTypes.REQUEST_INIT_DATA_FAILED: {
return {
...state,
app: {
notification: {
message: payload.message,
isError: true,
isShow: true
}
}
}
}
default:
return state
}
}