【问题标题】:redux async with redux thunk doesn't work with @connect带有 redux thunk 的 redux async 不适用于 @connect
【发布时间】:2018-07-22 19:30:32
【问题描述】:

我尝试使用 setTimeout 作为 rest api 的模拟,但我的 redux 似乎有缺陷。

https://codesandbox.io/s/1zr78rp48j

部分代码

@connect(state => state.items, { approveItem })
export default class Items extends Component {
  render() {
    return (
      <div>
        <div>status: {this.props.item.status}</div>
        <button onClick={() => approveItem()}>{this.props.loading ? 'loading...' : 'Approve'}</button>
      </div>
    );
  }
}

我想知道为什么这个简单的流程不起作用,我在 reducer 中的 setTimeout 函数有意义吗?我正在使用 redux-thunk。

【问题讨论】:

  • ”是我在减速器中的 setTimeout 函数有意义”减速器可以永远是异步的。 Redux thunk 允许你的 actions 是异步的。再次查看文档。
  • @FelixKling 那么如果没有像 fetch 和 axios 这样的真正的 api 库,它会是什么样子?

标签: javascript ecmascript-6 redux react-redux redux-thunk


【解决方案1】:

我已经更正了你的代码,看看

https://codesandbox.io/s/14j6m2661q

问题出在你的课堂上

export  class Items extends Component {
  render() {
    console.log(approveItem);
    return (
      <div>
        <div>status: {this.props.items && this.props.items.item.status}</div>
        <button onClick={() => this.props.approveItem()}>Approve </button>
      </div>
    );
  }
}

// start of code change
const mapStateToProps = (state) => {
  return { items: state.items };
};
const mapDispatchToProps = (dispatch) => {

  return {
    approveItem: () => dispatch(approveItem())
  };
};
export default connect(mapStateToProps, mapDispatchToProps)(Items);

【讨论】:

  • 噗...装饰器在哪里?问题的重点是为什么它不适用于 @connect 装饰器。
  • 这没有什么问题,只是在 onclick 监听器中使用“this.props.approveItem()”而不是调用“approveItem()”
  • @FadiAboMsalam 如果我使用装饰器,我在 this.props 中看不到approveItem 函数
  • 我可以确认我在 OP 提供的沙箱代码中所做的唯一更改是调用 this.props.approveItem() 并且它按预期工作。
  • @Sagivb.g stackoverflow.com/questions/48807783/… 看看这个奇怪的问题?
【解决方案2】:

如果您希望 redux 获取动作创建者并将它们包装在一个函数中,该函数将分派其结果,您必须将动作创建者 pass an object 作为 mapDispatchToProps 的成员(您这样做是正确的)。

但是在组件中你没有使用包装的动作创建器,你使用的是导入的approveItem 创建自动调度动作创建器的正确代码是:

import React, { Component } from "react";
import { connect } from "react-redux";
import { approveItem } from "./actions";
//mapDispatchToProps is an object here, all function members of the object
//  will be treated as action creators and wrapped in a function that when
//  called will automatically dispatch their result
const mapDispatchToProps = { approveItem };
@connect(state => state.items, mapDispatchToProps)
export default class Items extends Component {
  render() {
    //use the wrapped action creator found on this.props
    console.log(this.props.approveItem);
    return (
      <div>
        <div>status: {this.props.item.status}</div>
        <button onClick={() => this.props.approveItem()}>Approve </button>
      </div>
    );
  }
}

您可以手动将动作创建者包装在一个函数中,该函数将分派其结果(动作)。通过将函数传递给 mapDispatchToProps。

当您想要隔离组件并且不将所有减速器和操作都倾倒在一堆时,通常会出现这种情况。该应用程序将在{type:"ITEM",action:actualItemComponentAction} 中包装操作。由于组件不知道如何将其动作包装在应用程序处理的动作中,因此应用程序需要将包装器传递给动作创建者,这些创建者返回用于 thunk 的函数并使用应用程序减速器可以处理的类型包装实际动作对象。

不确定bindActionCreators 是如何适应这一点的,因为如果您想手动将动作创建者绑定到组件,您通常不想自动绑定它们,而是希望将组件动作包装在应用程序动作中。

可以在here找到一个正在进行的示例。

【讨论】:

  • 任何我需要bindActionCreators的线索我以前不使用它们中的任何一个,我的代码就可以工作了。
  • @JennyMok approveItem 只是创建一个动作(因为您已经认为该动作实际上是一个函数)但您没有调度它。即使approveItem 会创建一个动作对象,我怀疑它会被分派。也许您可以提供一个有效的代码示例?动作创建者通常只创建一个动作但不分派它,因此在点击处理程序中调用动作创建者函数不会做任何事情,除非您分派动作创建者的结果。
  • @JennyMok 如果你don't import the action creator 并使用const approveItem = () =&gt; ({ type: "APPROVED" }) 然后单击按钮时仍然不会发生任何事情。 approveItem 函数返回一个对象(动作),但它没有被分派,connect 只将approveItem 放在道具上,但在分派它的结果时没有做任何事情。
  • 在这个例子中github.com/eldyvoon/react-redux-express-auth/tree/master/src/… 不需要bindActionCreators,但为什么它仍然有效?
  • @JennyMok 更新了答案,mapDispatchToProps 接受一个带有动作创建者的对象,并将这些对象放在一个包装在一个函数中的道具上,该函数将自动发送它们的结果。您正确地完成了该部分,但在 onClick 函数中您没有使用它,您应该使用this.props.approveItem
猜你喜欢
  • 2021-09-11
  • 2019-04-20
  • 2016-06-12
  • 2019-11-14
  • 2017-03-27
  • 2019-09-09
  • 2020-07-21
  • 2022-12-21
  • 2019-06-15
相关资源
最近更新 更多