为啥我们已经有了 mapDispatchToProps 还需要 redux-thunk

Posted

技术标签:

【中文标题】为啥我们已经有了 mapDispatchToProps 还需要 redux-thunk【英文标题】:Why do we need redux-thunk when we already have mapDispatchToProps为什么我们已经有了 mapDispatchToProps 还需要 redux-thunk 【发布时间】:2017-11-13 13:36:47 【问题描述】:

Redux-thunk 允许您创建返回函数而不是动作的动作创建者。内部函数接收 store 方法 dispatch 和 getState 作为参数。

function incrementAsync() 
  return (dispatch, getState) => 
    setTimeout(() => 
       dispatch(increment());
    , 1000);
  ;

但与此同时,react-redux 的 connect 已经有一个 mapDispatchToProps 参数,可用于将动作创建者包装到调度调用中,以便可以直接调用它们。使用 mapDispatchToProps 你已经可以做到了,

const mapDispatchToProps = (dispatch) => (
  incrementAsync: () => 
    setTimeout(() => 
      dispatch(increment());
    , 1000);
  
);
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

在我看来,没有 redux-thunk 也可以做到这一点。为什么我们首先要有 redux-thunk 库?我确定我只是看不到它,因为 redux-thunk 是一个相当流行的库。

【问题讨论】:

【参考方案1】:

使用 redux-thunk 的一大优势是能够在确定操作时访问整个状态,这是仅使用 mapDispatchToProps 无法做到的。

首先你不能在 mapDispatchToProps 中获取整个状态可能看起来很奇怪,但这是有道理的,因为 mapDispatchToProps 可能只在第一次渲染时调用一次,因此传递给它的任何状态都可能是陈旧的调用其中一个操作的时间。

因此,您可以使用 redux-thunk,也可以将所需的全部状态作为 props 传递给组件来确定您的操作,这在某些情况下可能对渲染组件无用,从而触发不必要且可能代价高昂重新渲染,以便您的组件可以充当将数据传递给动作创建者的桥梁。

【讨论】:

【参考方案2】:

动作创建者可以是同步的或异步的。 redux-thunk 主要用于创建异步动作创建者,例如发送 API 调用,其中异步动作创建者调度另一个函数/动作创建者,而不是仅返回一个动作。 内部函数接收存储方法dispatchgetState 作为参数。

    将动作创建者包装到mapDispatchToProps 中的调度调用中不提供对getState 方法的访问。 redux-thunk 提供对dispatchgetState 的访问。

    export const actionCreator = () => 
        return (dispatch, getState) => 
        //axios call
        dispatch(anotherActionCreator());
      ;
    ;
    

    mapDispatchToProps 中使用动作创建者与使用动作创建者的封装和一致性冲突,因为组件不必知道创建和调度动作的细节,无论是简单返回动作对象还是一个复杂的 redux-thunk 异步操作创建者。

    单独创建动作创建者有助于我们在多个地方重用动作创建者。

【讨论】:

【参考方案3】:

您确实可以通过这种方式从您的操作中访问dispatch,但redux-thunk 可以在没有该包装函数和显式调度切换的情况下实现。

您还可以通过作为第二个参数提供的getState() 函数从您的操作中立即访问状态。

// actionFile.js
export someAction(dispatch) 
  return function(value) 
    dispatch( type: 'SOME_TYPE', value );
  


// component.jsx
const mapDispatchToProps = (dispatch) => (
  someAction: someAction(dispatch)
);

对比

// actionFile.js
export someAction(value) 
  return function(dispatch, getState) 
    dispatch( type: 'SOME_TYPE', value );
    // maybe do some stuff with getState()
  


// component.jsx
const mapDispatchToProps =  someAction ;

这绝对是可选的,但在我看来更简洁,最重要的是可以更好地分离组件和动作创建者之间的关注点。即,当您需要异步调度或触发副作用时,您无需对如何定义 mapDispatchToProps 大惊小怪。

【讨论】:

【参考方案4】:

除了 Redux Thunk,第一个例子还有两大优势:

    由于它是独立的且功能强大的,因此更易于测试,因此您只需 需要包含它并使用它以断言它的行为正确 (没有道具查询、模拟或浅渲染问题 如果它在组件中,您将拥有) 可以重复使用(第二个例子是不可能重复使用的)。想象一下,您必须从应用程序的多个位置分派相同的操作并使用第二种模式,复制代码,然后对操作的要求发生变化?

【讨论】:

【参考方案5】:

简而言之,您的解决方案完全没问题。

我认为使用 thunk 中间件的方便之处在于您可以以异步或不同方式处理任何操作创建者调用,这意味着您不必传递调度函数。每当你调度的是一个函数调度被注入到它的返回函数中。总而言之,使用 redux-thunk 使动作创建者可组合。

在此处查看 Dan Abramovs 的详细答案:How to dispatch a Redux action with a timeout?

还只是查看redux-thunk code 帮助我理解了这一点。

【讨论】:

以上是关于为啥我们已经有了 mapDispatchToProps 还需要 redux-thunk的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们已经有了 mapDispatchToProps 还需要 redux-thunk

当我们已经拥有更强大的向量时,为啥还需要堆栈?

有了Jenkins,为啥还需要一个独立的部署系统?

React Native 已经有了异步存储。为啥我应该在我的 react native 应用中使用 Redux 和 Redux Thunk?

当我们有常规数组时,为啥我们需要指向数组的指针?

C语言中已经有了malloc和free,为啥还需要new和delete?