目錄
一、redux介紹
二、安裝
三、基本實現步驟
3.1 創建Action Types
3.2 創建counterAction
3.3 創建counterReducer
3.4 結合所有Reducer
3.5 創建store
3.6 入口文件中提供store
3.7 在組件中的使用
3.8 使用thunk實現異步支持
3.8.1 安裝
3.8.2 在counterAction中添加異步操作
3.8.3 在store文件中添加異步支持
3.8.4 在組件中進行異步操作
3.9 函數式組件使用hooks代替connect
一、redux介紹
Redux 基于三個基本原則:
-
單一數據源:整個應用的狀態存儲在一個對象樹中
-
狀態是只讀的:唯一改變狀態的方法是觸發 action
-
使用純函數執行修改:reducer 是純函數,接收舊 state 和 action,返回新 state
二、安裝
npm install redux react-redux
三、基本實現步驟
3.1 創建Action Types
// actionTypes.js
export const INCREMENT = "INCREMENT";
export const DECREMENT = "DECREMENT";
3.2 創建counterAction
// store/actions/counterAction.jsimport { INCREMENT, DECREMENT } from "../../utils/actionTypes";export const increment = () => ({type: INCREMENT,
});export const decrement = () => ({type: DECREMENT,
});
3.3 創建counterReducer
// store/reducers/counterReducer.jsimport { INCREMENT, DECREMENT } from "../../utils/actionTypes";const initialState = {count: 0,
};export default function counterReducer(state = initialState, action) {switch (action.type) {case INCREMENT:return { ...state, count: state.count + 1 };case DECREMENT:return { ...state, count: state.count - 1 };default:return state;}
}
3.4 結合所有Reducer
// store/reducers/index.jsimport { combineReducers } from "redux";
import counterReducer from "./counterReducer";export default combineReducers({counter: counterReducer,
});
3.5 創建store
// store/index.js
import { createStore } from "redux";
import reducers from "./reducers";const store = createStore(reducers);export default store;
3.6 入口文件中提供store
// index.jsimport React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Provider store={store}><App /></Provider>
);
3.7 在組件中的使用
import React from "react";
import { connect } from "react-redux";
import { increment, decrement } from "./store/actions/counterAction";function App(props) {const { count, increment, decrement } = props;return (<div><div>數值:{count}</div><button onClick={() => increment()}>點我+1</button><button onClick={() => decrement()}>點我-1</button></div>);
}
const mapStateToProps = (state) => ({count: state.counter.count, // store/reducers/index.js中的counter映射
});const mapDispatchToProps = {increment,decrement,
};export default connect(mapStateToProps, mapDispatchToProps)(App);
3.8 使用thunk實現異步支持
3.8.1 安裝
npm install redux-thunk
3.8.2 在counterAction中添加異步操作
// store/actions/counterAction.jsimport { INCREMENT, DECREMENT } from "../../utils/actionTypes";export const increment = () => ({type: INCREMENT,
});export const decrement = () => ({type: DECREMENT,
});export const fetchIncrement = (timeout) => {return (dispatch) => {setTimeout(() => {dispatch(increment());}, timeout);};
};
3.8.3 在store文件中添加異步支持
// store.js
import { createStore, applyMiddleware } from "redux";
import { thunk } from "redux-thunk";
import reducers from "./reducers";const store = createStore(reducers, applyMiddleware(thunk));export default store;
3.8.4 在組件中進行異步操作
import React from "react";
import { connect } from "react-redux";
import {increment,decrement,fetchIncrement,
} from "./store/actions/counterAction";function App(props) {const { count, increment, decrement, fetchIncrement } = props;return (<div><div>數值:{count}</div><button onClick={() => increment()}>點我+1</button><button onClick={() => decrement()}>點我-1</button><button onClick={() => fetchIncrement(1000)}>點我異步+1</button></div>);
}
const mapStateToProps = (state) => ({count: state.counter.count, // store/reducers/index.js中的counter映射
});const mapDispatchToProps = {increment,decrement,fetchIncrement,
};export default connect(mapStateToProps, mapDispatchToProps)(App);
3.9 函數式組件使用hooks代替connect
// App.jsimport React from "react";
import { useSelector, useDispatch } from "react-redux";
import {increment,decrement,fetchIncrement,
} from "./store/actions/counterAction";export default function App(props) {const { count } = useSelector((state) => state.counter); // store/reducers/index.js中的counter映射const dispatch = useDispatch();return (<div><div>數值:{count}</div><button onClick={() => dispatch(increment())}>點我+1</button><button onClick={() => dispatch(decrement())}>點我-1</button><button onClick={() => dispatch(fetchIncrement(1000))}>點我異步+1</button></div>);
}