- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立一個事件感知元件
- ReactJS - 在 Expense Manager APP 中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 進行元件生命週期管理
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - 鍵
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - 地圖
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - 上下文
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - 片段
- ReactJS - 高階元件
- ReactJS - 與其他庫整合
- ReactJS - 最佳化效能
- ReactJS - Profiler API
- ReactJS - 埠
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - 調和
- ReactJS - Refs 和 DOM
- ReactJS - 渲染 Props
- ReactJS - 靜態型別檢查
- ReactJS - 嚴格模式
- ReactJS - Web Components
- 其他概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 走馬燈
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - 狀態管理
我們將執行以下操作來管理我們的 Redux 儲存。
透過非同步 fetch api 從伺服器獲取費用並將其設定為 Redux 儲存。
透過非同步 fetch 程式設計將新的費用新增到伺服器,並將新費用新增到 Redux 儲存中。
透過非同步 fetch api 從伺服器刪除現有費用並更新 Redux 儲存。
讓我們為管理 Redux 狀態建立動作型別、動作建立者、動作和 reducer。
在 src 資料夾下建立一個資料夾 actions。
接下來,建立一個檔案 types.js 來建立動作型別。
export const LIST_EXPENSE_STARTED = 'LIST_EXPENSE_STARTED'; export const LIST_EXPENSE_SUCCESS = 'LIST_EXPENSE_SUCCESS'; export const LIST_EXPENSE_FAILURE = 'LIST_EXPENSE_FAILURE'; export const ADD_EXPENSE_STARTED = 'ADD_EXPENSE_STARTED'; export const ADD_EXPENSE_SUCCESS = 'ADD_EXPENSE_SUCCESS'; export const ADD_EXPENSE_FAILURE = 'ADD_EXPENSE_FAILURE'; export const DELETE_EXPENSE_STARTED = 'DELETE_EXPENSE_STARTED'; export const DELETE_EXPENSE_SUCCESS = 'DELETE_EXPENSE_SUCCESS'; export const DELETE_EXPENSE_FAILURE = 'DELETE_EXPENSE_FAILURE';
接下來,在 actions 資料夾下建立一個檔案 index.js 來建立動作建立者。
import {
LIST_EXPENSE_STARTED, LIST_EXPENSE_SUCCESS, LIST_EXPENSE_FAILURE,
ADD_EXPENSE_STARTED, ADD_EXPENSE_SUCCESS, ADD_EXPENSE_FAILURE,
DELETE_EXPENSE_STARTED, DELETE_EXPENSE_SUCCESS, DELETE_EXPENSE_FAILURE,
} from "./types";
export const getExpenseListStarted = () => {
return {
type: LIST_EXPENSE_STARTED
}
}
export const getExpenseListSuccess = data => {
return {
type: LIST_EXPENSE_SUCCESS,
payload: {
data
}
}
}
export const getExpenseListFailure = error => {
return {
type: LIST_EXPENSE_FAILURE,
payload: {
error
}
}
}
export const addExpenseStarted = () => {
return {
type: ADD_EXPENSE_STARTED
}
}
export const addExpenseSuccess = data => {
return {
type: ADD_EXPENSE_SUCCESS,
payload: {
data
}
}
}
export const addExpenseFailure = error => {
return {
type: ADD_EXPENSE_FAILURE,
payload: {
error
}
}
}
export const deleteExpenseStarted = () => {
return {
type: DELETE_EXPENSE_STARTED
}
}
export const deleteExpenseSuccess = data => {
return {
type: DELETE_EXPENSE_SUCCESS,
payload: {
data
}
}
}
export const deleteExpenseFailure = error => {
return {
type: DELETE_EXPENSE_FAILURE,
payload: {
error
}
}
}
在這裡,我們為 fetch api 的每個可能的結果(成功、失敗和錯誤)建立了一個動作建立者。由於我們將使用三個 Web API 呼叫,並且每個呼叫將有三個可能的結果,因此我們使用 9 個動作建立者。
接下來,在 actions 資料夾下建立一個檔案 expenseActions.js,並建立三個函式來獲取、新增和刪除費用以及排程狀態更改。
import {
getExpenseListStarted, getExpenseListSuccess, getExpenseListFailure,
addExpenseStarted, addExpenseSuccess, addExpenseFailure,
deleteExpenseStarted, deleteExpenseSuccess, deleteExpenseFailure
} from "./index";
export const getExpenseList = () => async dispatch => {
dispatch(getExpenseListStarted());
try {
const res = await fetch('https://:8000/api/expenses');
const data = await res.json();
var items = [];
data.forEach((item) => {
let newItem = {
id: item._id,
name: item.name,
amount: item.amount,
spendDate: item.spend_date,
category: item.category
}
items.push(newItem)
});
dispatch(getExpenseListSuccess(items));
} catch (err) {
dispatch(getExpenseListFailure(err.message));
}
}
export const addExpense = (data) => async dispatch => {
dispatch(addExpenseStarted());
let newItem = {
name: data.name,
amount: data.amount,
spend_date: data.spendDate,
category: data.category
}
console.log(newItem);
try {
const res = await fetch('https://:8000/api/expense', {
method: 'POST',
body: JSON.stringify(newItem),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
const data = await res.json();
newItem.id = data._id;
dispatch(addExpenseSuccess(newItem));
} catch (err) {
console.log(err);
dispatch(addExpenseFailure(err.message));
}
}
export const deleteExpense = (id) => async dispatch => {
dispatch(deleteExpenseStarted());
try {
const res = await fetch('https://:8000/api/expense/' + id, {
method: 'DELETE'
});
const data = await res.json();
dispatch(deleteExpenseSuccess(id));
} catch (err) {
dispatch(deleteExpenseFailure(err.message));
}
}
這裡:
使用非同步 fetch api 進行 Web API 呼叫。
使用 dispatch 函式在成功、失敗和錯誤事件期間排程適當的動作。
在 src 資料夾下建立一個資料夾 reducers,並在 reducers 資料夾下建立一個檔案 index.js 來建立 Redux reducers。
import {
LIST_EXPENSE_STARTED, LIST_EXPENSE_SUCCESS, LIST_EXPENSE_FAILURE,
ADD_EXPENSE_STARTED, ADD_EXPENSE_SUCCESS, ADD_EXPENSE_FAILURE,
DELETE_EXPENSE_STARTED, DELETE_EXPENSE_SUCCESS, DELETE_EXPENSE_FAILURE
} from "../actions/types";
// define initial state of user
const initialState = {
data: null,
loading: false,
error: null
}
export default function expenseReducer(state = initialState, action) {
switch (action.type) {
case LIST_EXPENSE_STARTED:
return {
...state,
loading: true
}
case LIST_EXPENSE_SUCCESS:
const { data } = action.payload;
return {
...state,
data,
loading: false
}
case LIST_EXPENSE_FAILURE:
const { error } = action.payload;
return {
...state,
error
}
case ADD_EXPENSE_STARTED:
return {
...state,
loading: true
}
case ADD_EXPENSE_SUCCESS:
return {
...state,
loading: false
}
case ADD_EXPENSE_FAILURE:
const { expenseError } = action.payload;
return {
...state,
expenseError
}
case DELETE_EXPENSE_STARTED:
return {
...state,
loading: true
}
case DELETE_EXPENSE_SUCCESS:
return {
...state,
data: state.data.filter(expense => expense.id !== action.payload.data),
loading: false
}
case DELETE_EXPENSE_FAILURE:
const { deleteError } = action.payload;
return {
...state,
deleteError
}
default:
return state
}
}
在這裡,我們已為每個動作型別更新了 redux 儲存狀態。
接下來,開啟 src 資料夾下的 index.js 檔案,幷包含 Provider 元件,以便所有元件都可以連線並與 redux 儲存一起工作。
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import rootReducer from './reducers';
import App from './components/App';
const store = createStore(rootReducer, applyMiddleware(thunk));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
這裡:
- 匯入 createStore 和 applyMiddleware
- 從 redux-thunk 庫(用於非同步 fetch api)匯入 thunk
- 從 redux 庫匯入 Provider
- 透過配置 reducer 和 thunk 中介軟體使用 createStore 建立 newstore
- 將 Provider 元件作為頂級元件附加到 redux 儲存
reactjs_example.htm
廣告