Redux javascript
Redux是 JavaScript 應用程序的可預測狀態容器。css
隨着項目代碼的不斷豐富,項目中狀態和業務邏輯分散在每一個模塊裏。這讓組件的重複使用變得更加困難,也讓組件的數量愈來愈臃腫。Redux 會嘗試拆分 程序數據 和 業務邏輯,將它們放在 React 本身的容器中,這樣 React 就能夠專一於對 視圖的管理 了。這讓你的軟件變得更靈活。html
Redux的優缺點:java
優缺點並不全面
react
優點:webpack
一、數據流流動很天然,由於任何 dispatch 都會致使廣播,須要依據對象引用是否變化來控制更新粒度。git
二、若是充分利用時間回溯的特徵,能夠加強業務的可預測性與錯誤定位能力。github
缺點:
web
一、action和reducer太繁瑣。一套或者幾套action和reducer的組合,看起來很不錯,可是一旦功能和需求多了,action和reducer就會很混亂,若是管理不善,都不能愉悅的寫代碼了。npm
二、store和state的模棱兩可。沒有嚴格的定義哪些存store,哪些存internal state。
三、dispatch是同步的,並且dispatch沒辦法確認action是否執行成功。
並非全部狀況下 Redux 都是明智的選擇,應用 Redux 的場景:
* 你有着至關大量的、隨時間變化的數據
* 你的 state 須要有一個單一可靠數據來源
* 你以爲把全部 state 放在最頂層組件中已經沒法知足須要了
1、安裝
更目錄下運行命令安裝 redux
npm install --save redux
安裝 react-redux
npm install --save react-redux
安裝 react-logger
npm install --save redux-logger
2、編輯代碼
一、React 項目
代碼框架主要延用的是上一節 webpack4+react 配置出來的項目代碼。
項目github: https://github.com/Lyh97/wenpack4-react
二、action
Action 是把數據從應用傳到 store 的有效載荷。它是 store 數據的惟一來源。通常來講你會經過 store.dispatch()
將 action 傳到 store。
(1) 在 src下建立 constants 文件夾,其中建立 actionType.js 文件。
咱們約定,action 內必須使用一個 字符串類型 的 type
字段來表示將要執行的動做。多數狀況下,type
會被定義成 字符串常量。當應用規模愈來愈大時,建議使用 單獨的模塊或文件 來存放 action。所以咱們定義一個文件來專門存放 action 的 type常量。
actionType.js
export const HELLO_SET = 'HELLO_SET';
(2) src 下建立 action 文件夾,其中建立 index.js 和 hello.js
Action建立函數 就是生成 action 的方法。「action」 和 「action 建立函數」 這兩個概念很容易混在一塊兒,使用時最好注意區分。在 Redux 中的 action建立函數 只是簡單的返回一個 action :
hello.js
import * as actionTypes from '../constants/actionTypes'; export function setHello(hello) { return { type: actionTypes.HELLO_SET, hello }; };
index.js
import { setHello } from './hello'; export { setHello };
三、Reducers
Reducers 指定了應用狀態的變化如何響應 actions 併發送到 store 的,記住 actions 只是描述了有事情發生了這一事實,並無描述應用如何更新 state。
在 src 下建立 reducers 文件夾,其中建立 hello.js 以及 index.js。
hello.js
import * as actionTypes from '../constants/actionTypes'; const initialState = []; export default function(state = initialState, action) { switch (action.type) { case actionTypes.NAME_SET: return setHello(state, action); } return state; } function setHello(state, action) { const { hello } = action; return [ ...state, ...hello ]; }
index.js
import { combineReducers } from 'redux'; import name from './hello'; export default combineReducers({ hello });
四、Stores
action 來描述「發生了什麼」, reducers 來根據 action 更新 state 的用法。
Store 就是把它們聯繫到一塊兒的對象。強調一下 Redux 應用只有一個單一的 store。
Store 有如下職責:
getState()
方法獲取 state;dispatch(action)
方法更新 state;subscribe(listener)
註冊監聽器;subscribe(listener)
返回的函數註銷監聽器。
src 下建立 stores 文件夾,其中建立 configureStore.js
configureStore.js
import { createStore, applyMiddleware } from 'redux'; import rootReducer from '../reducers/index'; import { createLogger } from 'redux-logger'; const logger = createLogger(); const createStoreWithMiddleware = applyMiddleware(logger)(createStore); export default function configureStore(initialState) { return createStoreWithMiddleware(rootReducer, initialState); }
五、組件中的使用
src/index.js也須要編輯:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import AppTest from './App'; import * as serviceWorker from './serviceWorker'; import configureStore from './stores/configureStore'; import * as actions from './actions'; import { Provider } from 'react-redux'; const hello = 'Hello Word !!'; const store = configureStore(); store.dispatch(actions.setName(hello)); ReactDOM.render( <Provider store={store}> <AppTest /> </Provider>, document.getElementById('root')); serviceWorker.unregister();
我將 redux 用在了個人 App.jsx 組件裏 我在其中經過 {this.props.hello} 應用了 redux 中的變量 ,個人 App.jsx 是這麼寫的。
import React from 'react'; import { connect } from 'react-redux'; class AppTest extends React.Component { constructor(props) { super(props); this.state = { a: 2 } } render() { return ( <div> <p>{this.state.a}</p> {this.props.hello} </div> ) } } function mapStateToProps(state) { return { hello : state.hello } } export default connect(mapStateToProps)(AppTest);