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\
    • 匹配sagas.js中的设置,则执行sagas.js中对应的函数
    • 即在actionstore之间多了saga做中间处理
    //sagas.js
    
    import { takeEvery } from 'redux-saga/effects'
    
    function* <函数名>() {
    
    }
    
    function* mySaga() {
      yield takeEvery(, <函数名>);
    }
    
    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

理解:

  • 声明了其包裹的组件可以直接与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 = (
    //声明可以与store建立联系
                  //可以与store建议联系的组件
  
)

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

3.2 API:connect

只有包裹的组件才可以使用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 (    
      
    )
  }

}

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);

你可能感兴趣的:(Redux(0x02)-redux进阶)