React學習筆記6:使用react-redux更好的組織react和redux

新搭建的我的博客,本文地址: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')
);
相關文章
相關標籤/搜索