安裝 概念 在redux中分為3個對象:Action、Reducer、Store Action 1. 對行為(如用戶行為)的抽象 1. Action 就是一個普通 JavaScript 對象。如: (其中type欄位是約定也是必須的) 1. 作為Reducer的參數 Reducer 1. 一個普通的 ...
安裝
npm i -S redux react-redux redux-devtools
概念
在redux中分為3個對象:Action、Reducer、Store
Action
- 對行為(如用戶行為)的抽象
- Action 就是一個普通 JavaScript 對象。如:
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
(其中type欄位是約定也是必須的) - 作為Reducer的參數
Reducer
- 一個普通的函數,用來修改store的狀態。
- 函數簽名:
(currentState,action)=>newState
- 在 default 情況下返回currentState
Object.assign({},state, { visibilityFilter: action.filter })
(第一個參數不能為state) 等價於ES7的{ ...state, ...newState }
- redux 的 combineReducers 方法可合併reducer
Store
- 代表數據模型,內部維護了一個state變數
- 兩個核心方法,分別是getState、dispatch。前者用來獲取store的狀態(state),後者用來修改store的狀態
- createStore(reducer) 可創建Store
redux示例:
import { createStore } from 'redux'
// reducer
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
// state
let store = createStore(counter); // 會調用
// 監聽
store.subscribe(() =>
console.log(store.getState())
);
// 調用reducer
store.dispatch({ type: 'INCREMENT' });
react-redux
react的需求:
- 數據總是單向從頂層向下分發的
- 組件之間的溝通通過提升state:子組件改變父組件state的辦法只能是通過onClick觸發父組件聲明好的回調
- state越來越複雜:單頁應用的發展導致。包括伺服器響應、緩存數據、本地生成尚未持久化到伺服器的數據,也包括 UI 狀態,如激活的路由,被選中的標簽,是否顯示載入動效或者分頁器等等。
react-redux 將react組件分為2種:展示組件 和 容器組件
展示組件
描述如何展示:負責UI樣式的展示
- 數據來源:props
- 數據修改:通過props的回調函數
- 不直接使用redux
容器組件
描述如何運行:負責數據獲取 和 狀態更新
- 數據來源:redux state
- 數據修改:redux 派發action
- 直接使用redux
react-redux 只有2個API:Provider 和 connect
Provider
<Provider store>
- 在原應用組件上包裹一層,使原來整個應用成為Provider的子組件
- 接收Redux的store作為props,內部通過context對象傳遞給子孫組件上的connect
connect
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)
作用:連接React組件與 Redux store
mapStateToProps(state, ownProps) : stateProps
:
- 將 store 中的數據作為 props 綁定到組件上。
- 當 state 變化,或者 ownProps 變化的時候,mapStateToProps 都會被調用,計算出一個新的 stateProps
mapDispatchToProps(dispatch, ownProps): dispatchProps
:將 dispatch(action) 作為 props 綁定到組件上
mergeProps
:指定 stateProps 以及 dispatchProps 合併到 ownProps 的方式。(預設使用Object.assign)
connect是個高階組件(HOC)大致源碼:
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
return function wrapWithConnect(WrappedComponent) {
class Connect extends Component {
constructor(props, context) {
this.store = props.store || context.store
this.stateProps = computeStateProps(this.store, props)
this.dispatchProps = computeDispatchProps(this.store, props)
this.state = { storeState: null }
// 合併stateProps、dispatchProps、parentProps
this.updateState()
}
shouldComponentUpdate(nextProps, nextState) {
// 進行判斷,當數據發生改變時,Component重新渲染
if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
this.updateState(nextProps)
return true
}
}
componentDidMount() {
this.store.subscribe( () => this.setState({ storeState: this.store.getState() }) )
}
render() {
return (
<WrappedComponent {...this.nextState} />
)
}
}
return Connect;
}
}
react-redux示例:
Counter.js
import React, { Component } from 'react';
import { createStore, bindActionCreators } from 'redux';
import { Provider, connect } from 'react-redux';
function clickReduce(state = { todo: 1 }, action) {
switch (action.type) {
case 'click':
return Object.assign({}, state, { todo: state.todo + 1 });
default:
return state;
}
}
let store = createStore(clickReduce);
class Counter extends Component {
render() {
return (
<div>
<div>{this.props.todo}</div>
<button onClick={this.props.clickTodo}>Click</button>
</div>
)
}
}
// 方式1:
export default connect(state => ({ todo: state.todo }),
dispatch => ({ clickTodo: () => dispatch({ type: 'click' }) }))(Counter)
// 方式2:
export default connect(state => ({ todo: state.todo }),
dispatch => bindActionCreators({ clickTodo: () => ({ type: 'click' }) }, dispatch))(Counter);
index.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { render } from 'react-dom';
import Clock from './Clock'
render((
<Provider store={store}>
<Counter />
</Provider>), root);
在redux中,我們只能dispatch簡單的action對象。
對應的在react-redux中,我們只能定義同步的reducer方法。
下節將介紹在react-redux如何定義非同步方法。讓其更加適用於生產環境。