如何在获取数据时在 React Redux 应用程序中显示加载指标?[已关闭]

2022-08-30 05:43:09

我是 React/Redux 的新手。我在 Redux 应用程序中使用获取 API 中间件来处理 API。它是(redux-api-middleware)。我认为这是处理异步 API 操作的好方法。但是我发现有些情况是我自己无法解决的。

正如主页(生命周期)所说,获取 API 生命周期从调度CALL_API操作以调度 FSA 操作结束。

因此,我的第一个案例是在获取 API 时显示/隐藏预加载器。中间件将在开始时调度 FSA 操作,并在结束时调度 FSA 操作。这两个动作都是由化简器接收的,化简器应该只做一些正常的数据处理。没有 UI 操作,没有更多的操作。也许我应该将处理状态保存在状态中,然后在商店更新时呈现它们。

但是如何做到这一点呢?反应组件流遍整个页面?从其他操作更新商店会发生什么情况?我的意思是,它们更像是事件而不是状态!

更糟糕的是,当我必须在 redux/react 应用中使用本机确认对话框或警报对话框时,我该怎么办?它们应该放在哪里,行动还是减少?

愿你安好!希望回复。


答案 1

我的意思是,它们更像是事件而不是状态!

我不会这么说。我认为加载指标是UI的一个很好的例子,很容易被描述为状态的函数:在这种情况下,是布尔变量的函数。虽然这个答案是正确的,但我想提供一些代码来配合它。

Redux 存储库中的异步示例中,reducer 更新了一个名为 isFetching 的字段

case REQUEST_POSTS:
  return Object.assign({}, state, {
    isFetching: true,
    didInvalidate: false
  })
case RECEIVE_POSTS:
  return Object.assign({}, state, {
    isFetching: false,
    didInvalidate: false,
    items: action.posts,
    lastUpdated: action.receivedAt

该组件使用 React Redux 订阅存储的状态,并将 isFetch 作为 mapStateToProps() 返回值的一部分返回,以便它在连接的组件的 props 中可用:connect()

function mapStateToProps(state) {
  const { selectedReddit, postsByReddit } = state
  const {
    isFetching,
    lastUpdated,
    items: posts
  } = postsByReddit[selectedReddit] || {
    isFetching: true,
    items: []
  }

  return {
    selectedReddit,
    posts,
    isFetching,
    lastUpdated
  }
}

最后,该组件在 render() 函数中使用 isFetching prop 来呈现“正在加载...”。标签(可以想象是一个微调器):

{isEmpty
  ? (isFetching ? <h2>Loading...</h2> : <h2>Empty.</h2>)
  : <div style={{ opacity: isFetching ? 0.5 : 1 }}>
      <Posts posts={posts} />
    </div>
}

更糟糕的是,当我必须在 redux/react 应用中使用本机确认对话框或警报对话框时,我该怎么办?它们应该放在哪里,行动还是减少?

任何副作用(显示对话肯定是副作用)都不属于化简器。将化简器视为被动的“国家建设者”。他们并没有真正“做”事情。

如果要显示警报,请在调度操作之前从组件执行此操作,也可以从操作创建者执行此操作。在调度操作时,为时已晚,无法对其执行副作用。

对于每个规则,都有一个例外。有时,您的副作用逻辑非常复杂,以至于您实际上希望将它们耦合到特定的操作类型或特定的化简器。在这种情况下,请查看Redux SagaRedux Loop等高级项目。只有当你对vanilla Redux感到满意并且有一个真正的分散副作用问题时,你才会这样做,你想让它更易于管理。


答案 2

伟大的答案丹·阿布拉莫夫!只是想补充一点,我或多或少地在我的一个应用程序中做了同样的事情(将isFetching保留为布尔值),最终不得不将其设置为整数(最终读取为未完成请求的数量)以支持多个同时请求。

使用布尔值:

请求 1 开始 -> -> 请求 2 上的微调器开始 -> 请求 1 结束 -> 微调器关闭 -> 请求 2 结束

带整数:

请求 1 开始 -> -> 请求 2 开始 -> 请求 1 结束 -> 请求 2 结束 ->微调器关闭

case REQUEST_POSTS:
  return Object.assign({}, state, {
    isFetching: state.isFetching + 1,
    didInvalidate: false
  })
case RECEIVE_POSTS:
  return Object.assign({}, state, {
    isFetching: state.isFetching - 1,
    didInvalidate: false,
    items: action.posts,
    lastUpdated: action.receivedAt