npm i -S redux react-redux redux-devtools
react
在redux中分爲3個對象:Action、Reducer、Storenpm
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
(其中type字段是約定也是必須的)(currentState,action)=>newState
Object.assign({},state, { visibilityFilter: action.filter })
(第一個參數不能爲state) 等價於ES7的 { ...state, ...newState }
redux示例: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的需求:緩存
react-redux 將react組件分爲2種:展現組件 和 容器組件服務器
描述如何展現:負責UI樣式的展現app
描述如何運行:負責數據獲取 和 狀態更新dom
react-redux 只有2個API:Provider 和 connect異步
<Provider store>
ide
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)
函數
做用:鏈接React組件與 Redux store
mapStateToProps(state, ownProps) : 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如何定義異步方法。讓其更加適用於生產環境。