Redux(0x02)-redux进阶

Redux进阶

1 Redux-thunk 中间件

  • GIthub地址: Redux-thunk
  • Redux-thunk中间件的理解
    • 此中间件是指在actionstore中间 注意是Redux的中间件,而不是React的中间件
    • 此中间件就是对dispatch重新做了一次封装
      • 当传入的action是对象时 ,直接交给store处理
      • 当传入的action是函数时 ,先执行函数,若函数中有对象形式的action再交给store处理
1594129649773.png
  • 安装:

    npm install redux-thunk --save
    
  • 配置:

    • scr/store/index.js中配置 ---- 只有thunk中间件的情况
      • 1 添加applyMiddleware: 用于给Redux添加中间件
      • 2 导入redux-thunk
      • 3 添加thunk中间件
    import { createStore, applyMiddleware } from 'redux'   ----1----
    import thunk from 'redux-thunk';   -----2-----
    import reducer from './reducer'
    
    const store  = createStore(
      reducer, 
      applyMiddleware(thunk)  ------3-----
      //window....: 也是中间件  配合redux-devtools使用
    export default store
    
    • scr/store/index.js中配置 ---- 有多个中间件的情况
    import { createStore, applyMiddleware, compose } from 'redux'
    import thunk from 'redux-thunk';
    import reducer from './reducer'
    
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
    const enhancer = composeEnhancers(
      applyMiddleware(thunk)
    );
    
    const store  = createStore(
      reducer, 
      enhancer
    )
    
    export default store
    
  • 使用:

    • 网络请求写在src/store/actionCreator.js
      • dispatch : 直接将action传给store处理
      • 函数内可以直接调用actionCreator.js中的其他函数
    export const getTodoList = () => {
      return (dispatch) => {
        axios.get('http://152.136.185.210:8000/api/n3/home/multidata').then((res) => {
          const item = res.data.data.banner.list[0].acm
          const action = getAddItemAxios(item)
          dispatch(action)
        })
      }
    }
    
    • 组件中调用该网络请求函数
    import {getTodoList} from './store/actionCreators'
    
    const action = getTodoList()
    store.dispatch(action)
    

2 Redux-saga 中间件

  • Github地址: Redux-saga

  • 安装:

    npm install redux-saga --save
    
  • 配置:官方配置教程

    • src/store/index.js中配置
    import { createStore, applyMiddleware, compose } from 'redux'
    import createSagaMiddleware from 'redux-saga' //导入redux-saga
    import reducer from './reducer'
    import mySaga from './sagas'  // 导入saga文件 
    
    const sagaMiddleware = createSagaMiddleware() //实例化saga
    
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
    const enhancer = composeEnhancers(
      applyMiddleware(sagaMiddleware) //添加saga为redux的中间件
    );
    
    const store  = createStore(reducer, enhancer)
    sagaMiddleware.run(mySaga) // 执行saga文件
    
    export default store
    
  • 编辑sagas.js : 官方教程

    • src/store下新建sagas.js文件
    • 组件中创建action通过store.dispatch(action)会将action同时传给sagas.jsreducer.js\
    • <action.type>匹配sagas.js中的设置,则执行sagas.js中对应的函数
    • 即在actionstore之间多了saga做中间处理
    //sagas.js
    
    import { takeEvery } from 'redux-saga/effects'
    
    function* <函数名>() {
    
    }
    
    function* mySaga() {
      yield takeEvery(<action.type>, <函数名>);
    }
    
    export default mySaga;
    
  • saga中间件处理异步请求并更新store数据的流程

    • 1 定义actionsaga可以抓取
    //actionCreators.js
    export const getTodoList = () => ({
      type: GET_TODOLIST,
    })
    
    • 2 组件中实例化action并发送action
    const action = getTodoList()
    store.dispatch(action)
    
    • 3 sagas.js中接收action并发送网络请求
      • 网络请求不在使用promise.then()
      • 使用yield语法处理网络请求
      • put接口用于将action发送给store处理
    import { put, takeEvery } from 'redux-saga/effects'
    import axios from 'axios'
    import { GET_TODOLIST } from './actionTypes'
    import { getAddItemAxios } from './actionCreators'  //将请求的数据更新到store的action
    
    function* getTodolist() {
      const res = yield axios.get('http://152.136.185.210:8000/api/n3/home/multidata')
      const item = res.data.data.banner.list[0].acm
      const action = getAddItemAxios(item)
      yield put(action)
    }
    
    function* mySaga() {
      yield takeEvery(GET_TODOLIST, getTodolist);
    }
    
    export default mySaga;
    
    • 4 更新store数据
    //actionCreators.js
    export const getAddItemAxios = (item) => ({
      type: ADD_TO_LISTUP,
      item
    })
    
    //reducer.js
    if(action.type === ADD_TO_LISTUP){
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.push(action.item)
        return newState
      }
    

3 React-redux

  • Github地址:react-redux

  • 安装:

    npm install react-redux --save
    

3.1 API : Provider

理解:

  • <Provider>声明了其包裹的组件可以直接与store建立联系,通过API:connect更方便的获取和修改store中数据

使用:

//src/store/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
import {Provider} from 'react-redux'; //导入react-redux
import store from './store'   //导入store

const App = (
  <Provider store = {store}>  //声明可以与store建立联系
    <TodoList />              //可以与store建议联系的组件
  </Provider>
)

ReactDOM.render(App,document.getElementById('root'));

3.2 API:connect

只有<Provider>包裹的组件才可以使用connectstore建立连接

  1. 导入connect方法

    import { connect } from 'react-redux'
    
  2. 导出组件

    • 本质是返回connect函数的执行结果 其执行结果就是将派发action等业务逻辑加到了组件中
    export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
    
  3. 获取store数据的方式的改变

    • 不建立连接时的方式
    //1 导入store
    import store from './store/index'  
    //2 将store的所有数据赋值给组件的state
    this.state = store.getState()
    //3 通过this.state使用
    this.state.属性
    
    • 建立连接后的方式
    //1 将store中的数据单个的赋值给组件的props   ----注意:可以单个赋值-----
    const mapStateToProps = (state) => {
      return {
        inputValue: state.inputValue
      }
    }
    //2 通过this.props使用
    this.props.inputValue
    
  4. 修改store数据的方式的变化

    • 不建立连接时的方式
    // 1 派发action的函数写在组件中  通过this.dispatch派发
    class TodoList extends Component {
        constructor(props) {  
            super(props) 
            this.changeInputValue = this.changeInputValue.bind(this)
        }
        render() { }
        changeInputValue(e){
          const action = getInputChangeAction(e.target.value)
          this.dispatch(action)
        }
    }
    //2 通过this.函数名 调用函数   需要绑定this
    this.changeInputValue
    
    • 建立连接后的方式
    //1 派发action的函数写在mapDispatchToProps中  通过dispatch派发
    const mapDispatchToProps = (dispatch) => {
      return {
        changeInputValue(e){
          const action = getInputChangeAction(e.target.value)
          dispatch(action)
        }
      }
    }
    //2 通过this.props.函数名 调用函数   不需要绑定this
    this.props.changeInputValue
    
  5. store数据改变,组件绑定的数据或自动刷新,不需要再订阅store的变化

    store.subscribe(this.handleStoreChange)  //不再需要此订阅
    handleStoreChange() {
          this.setState(store.getState())
    }
    

案例:

//组件.js
import React, {Component} from 'react'
import { connect } from 'react-redux'
import {getInputChangeAction} from './store/actionCreators'
import TodoListUI from './TodoListUI'

class TodoList extends Component {
  constructor(props) {  
    super(props)       
    this.state = store.getState()
    store.subscribe(this.handleStoreChange)
  }


  render() {  
      
    return (    
      <TodoListUI
        inputValue = {this.props.inputValue}
        changeInputValue = {this.props.changeInputValue}/>
    )
  }

}

const mapStateToProps = (state) => {
  return {
    inputValue: state.inputValue
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    changeInputValue(e){
      const action = getInputChangeAction(e.target.value)
      dispatch(action)
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 一.引入: react本身是一个非常轻量级的视图层框架,因为组件传值太麻烦了。在react基础上配套一个数据层的框...
    Zlaojie阅读 166评论 0 0
  • 可有可无的 Redux 举例:需求是吃饭,React 是做饭的工具或者吃饱的途径,也就是解法。那么 Redux 是...
    扬仔360阅读 429评论 0 0
  • 为了学习React-Redux 基本用法 Redux官网 之前看过一次 云里雾里 也是难点 视图层框架 React...
    zz77zz阅读 1,641评论 0 0
  • Redux 的核心理念是严格的单向数据流,只能通过 dispatch(action) 的方式修改 store,流程...
    何蒙其实很好阅读 672评论 0 0
  • redux-saga 一个用于管理Redux应用异步操作的中间件,使副作用(数据获取、浏览器缓存获取)易于管理、运...
    hellomyshadow阅读 220评论 0 0