天天看點

學習react-redux

store三個基本原則

  • 整個應用隻有唯一一個可信資料源,也就是隻有一個 Store
  • State 隻能通過觸發 Action 來更改
  • State 的更改必須寫成純函數,也就是每次更改總是傳回一個新的State,在 Redux 裡這種函數稱為 Reducer
import { createStore } from 'redux';
//reducer
const initialState = {
 text: 'Hello',
 count: 0,
}
const reducer = (state = initialState, action) => {
 console.log(action.type)
 switch (action.type) {
   case 'CHANGE_TEXT':
     return Object.assign({},state,{
      text: state.text === 'Hello' ? 'world' : 'Hello'
    })
   case 'BUTTON_CLICK':
     return Object.assign({},state,{
      text: 'Hello world'
    })
   case 'totalCount': 
   // 傳遞參數時
   let count = state.count + action.params
     return Object.assign({},state,{count: count})
   default:
     return initialState;
 }
}

//store
let store = createStore(reducer);


export default store;
           

action基本結構

const changeTextAction = {
 type: 'CHANGE_TEXT'
}
const buttonClickAction = {
 type: 'BUTTON_CLICK'
}

// 需要傳遞參數時寫成這樣
let totalCountAction = (params) => {
  return {
    type: 'totalCount',
    params
  }
}

let action = {
 changeTextAction,
 buttonClickAction, 
 totalCountAction, 
}


export default action;
           

子元件中通路store

父元件

import React from 'react';
import Test from './pages/Test';
import { connect } from 'react-redux';
import action from './store/actions'
import PropTypes from 'prop-types'

import './App.css';

class App extends React.Component {
// 想要跨級通路時需要聲明
// ----------------------------------
  static childContextTypes = {
    store: PropTypes.object
}
getChildContext = () => {
  return {
    store: this.props
  }
}
//-----------------------------------
  render() {
    const { text, count, onButtonClick, onChangeText } = this.props;
    return (
      <div className="App">
        <button onClick={onButtonClick}>點選觸發1</button>
        <button onClick={() => onChangeText('333')}>點選觸發2</button>
        <div>{count}</div>
        <div>{text}</div>
        <Test />
      </div>
    );
  }
}

//映射Redux state到元件的屬性
function mapStateToProps(state) {
  return { text: state.text, count: state.count }
}

//映射Redux actions到元件的屬性
function mapDispatchToProps(dispatch) {
  return {
    onButtonClick: () => dispatch(action.buttonClickAction),
    // 傳遞參數時
    onChangeText: (params) => dispatch(action.totalCountAction(params))
  }
}

// 映射完成後可以this.props去通路

export default connect(mapStateToProps, mapDispatchToProps)(App);

           

子元件

import React,{Component} from 'react';
import PropTypes from 'prop-types'

class Test extends React.Component {
  constructor (props) {
   super(props);
   this.state = {

   }
  }
  // 跨級通路必備
  static contextTypes = {
    store: PropTypes.object
  }
  handleLeaveToShopkeeper = () => {
    console.log(this.context.store)
    this.context.store.onChangeText()
}
  componentDidMount() {
    const {store} = this.context;
    console.log(store)
  }

  render () {
    const {count} = this.context.store
   return (<div>跨級資料{count}<button onClick={this.handleLeaveToShopkeeper}>點選觸發</button></div>)
  }
}

export default Test;
           
mapStateToProps // 将state映射到props
mapdispatchToProps // 将dispatch映射到props
createStore(reducer) // 建立store存儲空間
connect(mapStateToProps,mapDispatchToProps,mergeProps,options) // 連結元件
childContextTypes // store跨級傳輸,頂級元件使用
getChildContext // store跨級傳輸,頂級元件使用
contextTypes // store跨級通路,子元件使用
           

connect詳解

ES7更新state

const initialState = {
  a: 'a',
  b: 'b'
};

function someApp(state = initialState, action) {
  switch (action.type) {
    case 'CHANGE_A':
      return { ...state, a: 'Modified a' };
    case 'CHANGE_B':
      return { ...state, b: action.payload };
    default:
      return state
  }
}




let state = {name: 'xyj',age: 18}
let stateOther = {...state,age: 19}
console.log(state) // {name: 'xyj', age: 18}
console.log(stateOther) // {name: 'xyj', age: 19}