为什么使用 Redux Thunk

IT技术 reactjs react-redux redux-thunk
2021-05-05 23:03:47

为什么使用 Redux Thunk 那么你可以做这样的事情:

ReadableAPI.getCategories().then((categories)=>{
      console.log('after getCategories', categories)

      this.props.dispatch(addCategories(categories))
    })

这不是更直接并达到同样的目的吗?

3个回答

Dan Abramov 的这个答案很好地解释了为什么要在应用程序中使用 redux-thunk。在您的应用程序中使用 redux-thunk 的另一个好处是您将业务逻辑与视图部分分开(在您的情况下是 React)。我们有一个用例,我们的应用程序是用它编写的backbone,我们想用 React 重写我们的整个应用程序。我们意识到如果您的视图和集合/模型是分开的,这很容易。我们开始只贬低 html 模板而不是集合。当我们弃用所有 html 模板时,我们开始Redux在我们的应用程序中使用并弃用我们的集合。

我想在这里说的是,我们将我们的逻辑viewbusiness逻辑分开,我们可以轻松地重构。类似地,使用Reactand 时Redux,您希望保持不同,这样如果有新事物出现并替换Redux,至少您不必弃用您的视图,而只需更改您的业务逻辑。

Redux Thunk基本上允许我们延迟一个动作的调度,即我们可以处理动作创建者返回的动作,并在我们真正想要调度时调用调度函数。

您的示例不完整,遵循您如何得出过于简单的解决方案令人沮丧。在研究它之后我意识到,你可能在ReadableAPI.js某个地方有一些你应该发布的文件,其中可能是使用 fetch 的配置,在它里面你可能有这样的东西:

export const getCategories = () =>
fetch('http://localhost:3001/categories', {headers})
  .then(res => res.json())
  .then(data => console.log(data))

这与您的:

ReadableAPI.getCategories().then((categories)=>{
   console.log('after getCategories', categories)

   this.props.dispatch(addCategories(categories))
})

因此,在此解决方案中,您将返回一个 Promise,它是一个对象,它基本上会在完成一些工作(例如网络请求)时向我们发出通知,并且为了获得通知,我们链接了.then()我们传递箭头函数的函数,就像您所做的那样:then((categories)=>并且该箭头函数将在未来的某个时间点被调用。

看起来您指的是该数据,categories并且您正在使用控制台日志记录'after Categories', categories

我们需要知道的是,附加到该categories对象上的不同属性是什么data有财产吗?它是否具有results包含一些实际数据属性?是否有categories.data.results包含任何数据的内容?

所以让我们说所有问题的答案都是肯定的。

为了处理异步请求,您正在以一种有点困难的方式进行处理,因为它不仅是代码片段,还有ReadableAPI.js文件中的内容,对吗?此外,您使用的 Promises 可能有点麻烦,并且您已经将两个文件放在一起来处理异步请求,如果它只是一个普通的 Reactjs 应用程序就可以了,但是您提到了您的方法作为 Redux 的替代方案-Thunk 这意味着使用 Redux。

对于您在 vanilla Reactjs 空间中的方法,我将使用 Axios 并实现async/await语法,但是在涉及 Redux 的情况下,您不想使用 Promise。

现在,我必须在ReadableAPI.js文件中创建的动作创建器在 Redux 环境中无法工作,因为它不返回普通的 JavaScript 动作对象,因此我们必须按照错误提示使用自定义中间件。

那么像 Redux-Thunk 这样的中间件是如何工作的呢?

Redux Thunk 本质上放宽了关于动作创建者的规则。

Redux-Thunk 的目的不是传递一个请求对象,它会带走它并为你工作。

Redux-Thunk 是一个通用中间件,它允许我们处理异步动作创建者,但它也允许我们做许多其他事情。

使用 Redux Thunk,你的动作创建者可以返回一个动作对象。如果你返回一个动作对象,它仍然必须有一个类型属性,如果它是一个被返回的动作对象,它也可以选择有一个有效负载。

Redux-Thunk 做的另一件事是允许你返回一个动作对象或一个函数。

如果您返回一个函数,Redux-Thunk 会自动为您调用该函数。

就是这样,这就是 Redux-Thunk 所做的。然而,Redux-Thunk 做得非常好的一件事是手动调度一个动作。那是关键部分。使用 Redux-Thunk,我们可以在未来的某个时间点手动调度一个动作。

所以我们创建了这个新动作,它可以是一个普通的 JavaScript 对象或一个函数,但是当我们在 Redux-Thunk 或函数内部手动调度它时,它基本上总是一个普通对象。

所以我们将调度这个动作,它会流回 dispatch 并且 dispatch 会将它直接发送回 Redux-Thunk,Redux-Thunk 会询问它是一个动作还是对象。

当它是一个对象时,Redux-Thunk 会自动将其转发给所有不同的减速器。

使用 Redux-Thunk,我们可以返回一个函数,如果我们这样做,该函数将被调用dispatchgetState参数,并且通过这两个函数,我们对 Redux 存储拥有无限的权力,我们可以在任何时间点更改任何数据并读取任何数据将来我们可以手动调度一个动作并更新我们商店内的数据。

我在哪里得到dispatchgetState来自 Redux-Thunk 库源代码:https : //github.com/reduxjs/redux-thunk/blob/master/src/index.js

src/index.js

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

如果您查看 if 条件,您会看到正在发生的实际逻辑的主体。你刚刚发送了一个动作吗?如果是,它是一个函数吗?如果是,那么 Redux Thunk 将使用dispatch调用该操作getState

如果我们的 action 不是函数,Redux-Thunk 不关心它,所以它会按照 指示的那样转到下一个中​​间件return next(action);,否则如果没有中间件要运行,则转到减速器。