redux-saga项目结构(附redux-thunk初始化代码)

项目结构

  • public

  • src

    • store redux仓库目录

      • actionCreators.js action目录

      • actionTypes.js action type目录

      • index.js redux入口文件,生成store

      • reducer.js redux逻辑文件,编写各个action所对应的逻辑

      • sagas.js saga逻辑文件,根据type捕捉相应action进行中间处理

    • index.js react项目入口文件

    • TodoList.js 组件

    • TodoListUI.js redux逻辑文件,编写各个action所对应的逻辑

  • package.json

  • README.md

可见项目结构随着redux-saga中间件的添加,并没有太多的变化。

其中主要发生改变的有store/index.js,以及新添加的store/sagas.js文件。

TodoListUI.js为为了将逻辑分离而单提出来的组件。

结构更改

TodoList的逻辑分离

TodoListUI

 import React from 'react';
 ​
 const TodoListUI = (props) => {
     const {inputValue, list, handleInputChange, handleButtonClick, handleLiClick} = props
     return (
         <div>
             <div>
                 <input value={inputValue} onChange={handleInputChange}></input>
                 <button onClick={handleButtonClick}>确定</button>
             </div>
             <ul>
                 {list.map((item, index)=> (
                     <li key={index} onClick={()=>handleLiClick(index)}>{item}</li>
                 ))}
             </ul>
         </div>
     )
 }
 ​
 ​
 export default TodoListUI

TodoListUI为一个无状态组件,接收一个参数并render一个组件。

TodoList

 import React, { Component } from 'react';
 import TodoListUI from './TodoListUI';
 import { connect } from 'react-redux'
 import { buttonClickAction, didMountAction, inputChangeAction, itemClickAction } from './store/actionCreators';
 ​
 class TodoList extends Component {
 ​
     componentDidMount() {
         this.props.didMount()
     }
 ​
     render() {
         const { inputValue, list, handleInputChange, handleButtonClick, handleLiClick } = this.props
         return (
             <TodoListUI
                 inputValue={inputValue}
                 list={list}
                 handleInputChange={handleInputChange}
                 handleButtonClick={handleButtonClick}
                 handleLiClick={handleLiClick}
             />
         );
     }
 }
 ​
 const stateToProps = (state) => {
     return {
         inputValue: state.inputValue,
         list: state.valueList
     }
 }
 ​
 const dispatchToProps = (dispatch) => {
     return {
         handleInputChange(e) {
             //dispatch(action)
         },
         handleButtonClick() {
             //dispatch(action)
         },
         handleLiClick(index) {
             //dispatch(action)
         },
         didMount(){
             const action = didMountAction()
             dispatch(action)
         }
     }
 }
 ​
 export default connect(stateToProps, dispatchToProps)(TodoList)

由代码可见TodoList相比于我们上次react-redux中的TodoList并没有发生太大改变,其主要变化有:

  • 增加componentDidMount函数,并在其中调用一个应用redux-saga的action

  • 将UI分离到另一个文件

redux-saga的新增代码

store/index.js

 import { createStore, applyMiddleware, compose } from 'redux'
 import reducer from './reducer'
 import createSagaMiddleware from 'redux-saga'
 import mySaga from './sagas'
 ​
 const sagaMiddleware = createSagaMiddleware()
 const dev_enhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
 const enhancer = dev_enhancer(applyMiddleware(sagaMiddleware))
 ​
 const store = createStore(
     reducer,
     enhancer
 )
 ​
 sagaMiddleware.run(mySaga)
 ​
 export default store

代码相对于上次主要改动的地方有两个方面:

  • redux-saga的使用

  • 增强函数实现dev tool于redux-saga的同时使用

redux-saga的使用

 import { createStore, applyMiddleware } from 'redux'
 import createSagaMiddleware from 'redux-saga'
 import mySaga from './sagas'
 ​
 const sagaMiddleware = createSagaMiddleware()
 ​
 const store = createStore(
     reducer,
     applyMiddleware(sagaMiddleware)
 )
 ​
 sagaMiddleware.run(mySaga)
 ​
 export default store

如果不使用调试工具,则redux-saga增加的代码如上,由此可见,redux-saga的初始化步骤为:

  1. 从redux引入applyMiddleware函数实现添加中间件

  2. 从redux-saga引入createSagaMiddleware函数用于生成一个sagaMiddleware

  3. 从自己创建的sagas.js文件中引入saga处理逻辑

  4. 创建sagaMiddleware

  5. 应用sagaMiddleware

  6. 启动sagaMiddleware

增强函数

 import { createStore, applyMiddleware, compose } from 'redux'
 import reducer from './reducer'
 import thunk from 'redux-thunk'
 ​
 const dev_enhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
 const enhancer = dev_enhancer(applyMiddleware(thunk))
 ​
 const store = createStore(
     reducer,
     enhancer
 )
 ​
 export default store

我们使用redux-thunk的初始化过程来讲解增强函数,同时记录下这个功能类似的中间件的初始化过程。

由于createStore函数无法同时接收dev tools与中间件,因此需要使用增强函数来实现这个功能。

增强函数,即返回一个函数的函数。在这个代码中,我们定义了一个dev tool的增强函数,并在其中传入了applyMiddleware函数作为参数,由此实现了两者的同时使用。

store/sagas.js

 import { DID_MOUNT } from "./actionTypes"
 import { takeEvery, put } from 'redux-saga/effects'
 import { sagaAction } from './actionCreators'
 ​
 function* mySaga() {
     yield takeEvery(DID_MOUNT, didMount)
 }
 ​
 ​
 function* didMount() {
     const action = sagaAction()
     yield put(action)
 }
 ​
 export default mySaga

sagas主要暴露一个函数,在这个函数中建立中间件内action type与行为的对应关系。需要注意的是这个文件里的函数必须为generate函数。takeEvery与put必须使用yield语句。

在本例中,saga捕捉所有type为DID_MOUNT的action,并通过didMount函数进行处理,处理完成后,生成一个新的action,并通过put将action传入reducer进行处理。

thunk与saga的区别

在学习的过程中,我同时学习了两个相似的中间件,即thunk与saga。在我看来,两者主要的区别在于:

  • thunk结构简单,saga结构复杂

  • thunk引入后,action从必须为对象变成了既可以是对象又可以是函数,函数的action会运行内部的逻辑,进行处理后dispatch一个新的action给reducer,从而实现reducer作为纯函数不能实现的功能。saga并没有改变action的类型,而是作为一个假的reducer捕获指定类型的action,进行处理后put(即dispatch的API)一个新的action给reducer。

  • thunk并没有在项目结构中添加新的结构,处理逻辑保存在actionCreator中。saga增添sagas文件并将所有中间处理的逻辑放到这个文件中集中管理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值