新搭建的我的博客,本文地址:React學習筆記6:使用react-redux更好的組織react和redux
很久沒有更新,一是最近太忙,二是redux我理解沒那麼深,從面相對象架構,要轉變爲函數式編程架構,以致於細節點拿不許,這個最小代碼抽了好久才抽出來,並且不能保證理解徹底正確,因此也歡迎拍磚。react
上一篇筆記,以最小化的代碼模擬了redux的核心,actions、reduces如何運行,這篇筆記首先對上面的代碼作初略的改造,把store放到組件外面,盡最大可能讓組件獨立npm
import React from 'react' import ReactDom from 'react-dom' import { createStore } from 'redux' class Hello extends React.Component { constructor(props) { super(props) this.state = { msg: 'Hello World!' } store.subscribe(() => { console.log('store_0 has been updated. Latest store state:', store.getState()); // 更新你的React數據 this.setState({ msg: store.getState().msg }) }) } changeLang = () => { //this.setState({msg:'您好,世界!'}) store.dispatch(actions.sendShowChineseMsg()) setTimeout(() => { store.dispatch(actions.sendShowEnglishMsg()) }, 5000) } render() { return ( <div> <button onClick={this.changeLang}>翻譯</button> {this.state.msg} </div> ) } } const reducer = (state = {}, action) => { console.log('reducer init state ', state, ' action ', action); switch (action.type) { case 'chinese': return { state, msg: '您好,世界!' } case 'english': return { state, msg: "Hello World!" } default: return state } } const actions = { sendShowChineseMsg: () => ({ type: 'chinese'}), sendShowEnglishMsg: () => ({ type: 'english'}) } const store = createStore(reducer) ReactDom.render( <Hello />, document.getElementById('example') );
能夠看到,不管如何store和組件仍是融合在一塊兒,這其中主要是state傳值,組件須要從store獲取值,另外一個就是觸發actions的click操做,須要dispatch,觸發store的subscribe。編程
react-redux組件就是解決此問題。react-redux把組件外面再包一層,稱之爲container,container,組件不須要本身從store得到值,container直接傳給組件,actions一樣同樣,都由container傳遞,這樣組件就跟操做props同樣,使用數值、函數,保證了組件的獨立性。redux
包這一層就是使用的react-redux提供的connect函數,connect函數原型以下架構
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
暫且不關注第三第四個參數,第一參數mapStateToProps就是映射到組件內要傳遞的props,第二個mapDispatchToProps則是映射到組件內actions,connect函數返回一個函數wrapWithConnect(WrappedComponent),該函數惟一參數是傳遞一個組件,須要被包起來的組件。app
//首先安裝react-redux組件 npm install --save react-redux
一、爲了模擬react-redux工做,首先須要把組件拆分爲兩個,其中一個Button組件,用來發送消息,另一個組件就是展現信息dom
class Hello extends React.Component { render() { return ( <span>{this.props.msg}</span> ) } } //暫且將onClick放上,該函數是由mapTranslateDispatchToProps傳遞而來 class Translate extends React.Component { render() { return ( <button onClick={this.props.sendMsg}>翻譯</button> ) } }
二、利用connect綁定state到Hello組件,綁定actions到Translate組件ide
const mapHelloStateToProps = (state, ownProps) => { console.log('mapStateToProps', state, ownProps) return { msg: state.msg ? state.msg : ownProps.msg } } //該組件只是展現信息,不須要connect actions,故不須要第二個參數 const HelloWorld = connect(mapHelloStateToProps)(Hello) const mapTranslateDispatchToProps = (dispatch, ownProps) => { return { sendMsg: () => { dispatch(actions.sendShowChineseMsg()) setTimeout(() => dispatch(actions.sendShowEnglishMsg()), 5000) } } } //該組件須要發送actions msg,不須要state,第一個參數傳遞null const TranslateButton = connect(null, mapTranslateDispatchToProps)(Translate)
三、利用一個頂層組件,把兩個組件串聯起來函數式編程
class App extends React.Component { render() { return ( <div> <TranslateButton /> <HelloWorld msg="Hello World!" /> </div> ) } }
四、利用react-redux的Provider組件,把store跟App組件連起來函數
ReactDom.render( <Provider store = {store}> <App /> </Provider>, document.getElementById('example') );
修改完畢後運行便可!
五、如下是完整代碼,以後要對代碼組織結構作一個調整
import React from 'react' import ReactDom from 'react-dom' import { createStore } from 'redux' import {connect,Provider} from 'react-redux' class Hello extends React.Component { render() { return ( <span>{this.props.msg}</span> ) } } class Translate extends React.Component { render() { return ( <button onClick={this.props.sendMsg}>翻譯</button> ) } } const reducer = (state = {}, action) => { console.log('reducer init state ', state, ' action ', action); switch (action.type) { case 'chinese': return { state, msg: '您好,世界!' } case 'english': return { state, msg: "Hello World!" } default: return state } } const actions = { sendShowChineseMsg: () => ({ type: 'chinese' }), sendShowEnglishMsg: () => ({ type: 'english' }) } const mapHelloStateToProps = (state, ownProps) => { console.log('mapStateToProps', state, ownProps) return { msg: state.msg ? state.msg : ownProps.msg } } const HelloWorld = connect(mapHelloStateToProps)(Hello) const mapTranslateDispatchToProps = (dispatch, ownProps) => { return { sendMsg: () => { dispatch(actions.sendShowChineseMsg()) setTimeout(() => dispatch(actions.sendShowEnglishMsg()), 5000) } } } const TranslateButton = connect(null, mapTranslateDispatchToProps)(Translate) class App extends React.Component { render() { return ( <div> <TranslateButton /> <HelloWorld msg="Hello World!" /> </div> ) } } const store = createStore(reducer) ReactDom.render( <Provider store = {store}> <App /> </Provider>, document.getElementById('example') );