redux(三)react-redux容器組件鏈接UI組件映射store中的state到props

cnpm i react-redux,然後在App.js中引入react-redux的Provider組件(react-redux的容器組件,始終在最外層),引入當前目錄下store下的store.js,將store傳遞給Provider組件:

App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Todos from "./components/Todos"
import Number2 from './Number2'

import {Provider} from 'react-redux';
import store from './store/store';
class App extends Component {
  render() {
    return (
    	<Provider store={store}>
		    <div className="App">
		        <Todos />
		        <hr/>
		        <Number2/>
		    </div>
      </Provider>
    );
  }
}

export default App;

在Number2組件中引入react-redux的connect函數,不再需要之前的actions.js文件了,但是需要actionCreator.js:

import React, { Component } from 'react';
// import actions from "../store/number/actions";不需要了
// import store from "../store/store";不需要了
import actionCreator from "../store/number/actionCreator"; //需要actionCreator中的action
import {connect} from 'react-redux';
class Number2 extends Component {
  constructor(){
    super();
    this.state = {
    	val: "0"
    }
  }
  render() {
  	console.log(this.props)
    return (
      <div>
        <button>++</button>
        <input type="text" />
        <button >--</button>
      </div>
    );
  }
}

let Connected = connect(state=>state)(Number2);//此時就能獲取store中的state了,14行測試打印結果

export default Connected;

14行輸出之前定義的state:


connect函數可以接受兩個參數,兩個都是回調函數,第一個回調函數中接收store中的state,意思是將store中的state映射到Number2組件的props中,第二個回調函數中接收store的dispatch,返回一個對象,對象包含所需的action的dispatch函數:

import React, { Component } from 'react';
// import actions from "../store/number/actions";不需要了
// import store from "../store/store";不需要了
import actionCreator from "../store/number/actionCreator"; //需要actionCreator中的action
import {connect} from 'react-redux';
class Number2 extends Component {
  constructor(){
    super();
    this.state = {
    	val: "0"
    }
  }
  render() {
  	console.log(this.props)
    return (
      <div>
        <button>++</button>
        <input type="text" />
        <button >--</button>
      </div>
    );
  }
}

let mapDispatchToProps = (dispatch)=>{
	return {
		add(){
			dispatch(actionCreator.intNumber());
		},
		sub(){
			dispatch(actionCreator.decNumber());
		},
		input(val){
			dispatch(actionCreator.inputNumber(val));
		}
	}
}

let Connected = connect(state=>state, mapDispatchToProps)(Number2);//鏈接容器組件到UI組件,此時就能獲取store中的state了,14行測試打印結果
/*connect函數可以接受兩個參數,兩個都是回調函數,第一個回調函數中接收store中的state,return state或一個對象,
意思是將store中的state映射到Number2組件的props中,第二個回調函數中接收store的dispatch,
返回一個對象,對象包含所需的action的dispatch函數*/


export default Connected;

此時Number2組件中就直接在props中獲取併發送對應的action了:


import React, { Component } from 'react';
// import actions from "../store/number/actions";不需要了
// import store from "../store/store";不需要了
import actionCreator from "../store/number/actionCreator"; //需要actionCreator中的action
import {connect} from 'react-redux';
class Number2 extends Component {
  // constructor(){
  //   super();
  //   this.state = {
  //   	val: "0"
  //   }
  // }
  render() {
  	console.log(this.props)
  	let {add, sub, input, number} = this.props;
    return (
      <div>
        <button onClick={add}>++</button>
        <input type="text" value={number.number} onChange={(e)=>input(e.target.value)}/>
        <button onClick={sub}>--</button>
      </div>
    );
  }
}

let mapDispatchToProps = (dispatch)=>{
	return {
		add(){
			dispatch(actionCreator.intNumber());
		},
		sub(){
			dispatch(actionCreator.decNumber());
		},
		input(val){
			dispatch(actionCreator.inputNumber(val));
		}
	}
}

let Connected = connect(state=>state, mapDispatchToProps)(Number2);//鏈接容器組件到UI組件,此時就能獲取store中的state了,14行測試打印結果
/*connect函數可以接受兩個參數,兩個都是回調函數,第一個回調函數中接收store中的state,return state或一個對象,
意思是將store中的state映射到Number2組件的props中,第二個回調函數中接收store的dispatch,
返回一個對象,對象包含所需的action的dispatch函數*/


export default Connected;

測試沒毛病!

不過這種方式需要一條一條手動寫出每個action才能映射到props,還有一種方式,引入redux的bindActionCreators,再將上面代碼改爲如下:

import React, { Component } from 'react';
// import actions from "../store/number/actions";不需要了
// import store from "../store/store";不需要了
import actionCreator from "../store/number/actionCreator"; //需要actionCreator中的action
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

class Number2 extends Component {
  render() {
  	console.log(this.props)
  	// let {add, sub, input, number} = this.props;
    // return (
    //   <div>
    //     <button onClick={add}>++</button>
    //     <input type="text" value={number.number} onChange={(e)=>input(e.target.value)}/>
    //     <button onClick={sub}>--</button>
    //   </div>
    // );
    let {methods, number} = this.props;
    return (
      <div>
        <button onClick={methods.intNumber}>++</button>
        <input type="text" value={number.number} onChange={(e)=>methods.inputNumber(e.target.value)}/>
        <button onClick={methods.decNumber}>--</button>
      </div>
    );
  }
}

let mapDispatchToProps = (dispatch)=>{
	return {
		// add(){
		// 	dispatch(actionCreator.intNumber());
		// },
		// sub(){
		// 	dispatch(actionCreator.decNumber());
		// },
		// input(val){
		// 	dispatch(actionCreator.inputNumber(val));
		// }

		/*傳入actionCreator和dispatch,此時無論有多少action全都映射到props.methods中,相當於語法糖*/
		methods: bindActionCreators(actionCreator, dispatch)
	}
}

let Connected = connect(state=>state, mapDispatchToProps)(Number2);//鏈接容器組件到UI組件,此時就能獲取store中的state了,14行測試打印結果
/*connect函數可以接受兩個參數,兩個都是回調函數,第一個回調函數中接收store中的state,return state或一個對象,
意思是將store中的state映射到Number2組件的props中,第二個回調函數中接收store的dispatch,
返回一個對象,對象包含所需的action的dispatch函數*/


export default Connected;

同樣connect函數的第一個函數參數也可以提取出來,提取出來有一個好處,可以定義一個類似計算屬性的屬性:

let mapDispatchToProps = dispatch=>{
	return {
		// add(){
		// 	dispatch(actionCreator.intNumber());
		// },
		// sub(){
		// 	dispatch(actionCreator.decNumber());
		// },
		// input(val){
		// 	dispatch(actionCreator.inputNumber(val));
		// }

		/*傳入actionCreator和dispatch,此時無論有多少action全都映射到props.methods中,相當於語法糖*/
		methods: bindActionCreators(actionCreator, dispatch)
	}
}

let mapStateToProps = state=>{
	return {
		number: state.number,
		numberSquare: Math.pow(state.number.number, 2)//將第一個函數提出來寫的好處就在這
	}
}

// let Connected = connect(state=>state, mapDispatchToProps)(Number2);//鏈接容器組件到ui,此時就能獲取store中的state了,14行測試打印結果
/*connect函數可以接受兩個參數,兩個都是回調函數,第一個回調函數中接收store中的state,return state或一個對象,
意思是將store中的state映射到Number2組件的props中,第二個回調函數中接收store的dispatch,
返回一個對象,對象包含所需的action的dispatch函數*/
let Connected = connect(mapStateToProps, mapDispatchToProps)(Number2)

export default Connected;

點擊++:


小結:其實主要就是利用react-redux的connect鏈接容器組件和UI組件,同時用了redux的bindActionCreators語法糖,從而省略掉了之前的actions.js文件,不再需要此文件了,因爲react-redux封裝了actions。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章