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

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

如首页(Lifecycle)所述,获取API的生命周期始于调度CALL_API操作,然后终止于调度FSA操作。

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

但是该怎么做呢?一个React组件流遍及整个页面吗?通过其他操作更新商店会发生什么?我的意思是,他们更像是事件而不是状态!

更糟糕的是,当我必须在Redux / React应用程序中使用本机确认对话框或警报对话框时,该怎么办?应该将它们放在哪里,采取什么行动或减少压力?

最好的祝愿!希望得到答复。

GreenA2020/03/12 15:07:04

我正在保存以下网址:

isFetching: {
    /api/posts/1: true,
    api/posts/3: false,
    api/search?q=322: true,
}

然后我有一个记忆的选择器(通过重新选择)。

const getIsFetching = createSelector(
    state => state.isFetching,
    items => items => Object.keys(items).filter(item => items[item] === true).length > 0 ? true : false
);

为了使POST时的网址唯一,我将一些变量作为查询传递。

在要显示指标的地方,我只需使用getFetchCount变量

2020/03/12 15:07:04

我是唯一一个认为加载指标不属于Redux商店的人吗?我的意思是,我不认为这本身就是应用程序状态的一部分。

现在,我使用Angular2,我要做的是我有一个“加载”服务,该服务通过RxJS BehaviourSubjects公开了不同的加载指示符。我猜想机制是相同的,只是我不将信息存储在Redux中。

LoadingService的用户只需订阅他们想收听的事件。

每当需要更改时,我的Redux操作创建者都会调用LoadingService。UX组件订阅公开的可观察对象...

梅西里2020/03/12 15:07:04

很好的答案Dan Abramov!只是想补充一点,就是我在一个应用程序中所做的工作或多或少完全相同(将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
Eva西里2020/03/12 15:07:04

我想加些东西。真实示例使用isFetching商店中的字段来表示何时提取项目集合任何集合都归纳为化pagination简器,可将其连接到组件以跟踪状态并显示集合是否正在加载。

碰巧我想获取不适合分页模式的特定实体的详细信息。我想有一个状态来表示是否正在从服务器中获取详细信息,但是我也不想为此而使用化简器。

为了解决这个问题,我添加了另一个通用的reducer fetching它的工作方式与分页减速器类似,它的职责只是观察一组动作并成对产生新状态[entity, isFetching]这就使connectreducer可以使用任何组件,并知道应用程序当前是否不仅在为集合而且为特定实体获取数据。

Pro梅2020/03/12 15:07:04

您可以使用connect()React Redux或低级store.subscribe()方法将更改侦听器添加到您的商店您应该在商店中有加载指示器,商店更改处理程序可以使用该指示器检查并更新组件状态。然后,如果需要,组件将根据状态呈现预加载器。

alert并且confirm不应该是一个问题。他们处于阻止状态,警报甚至不接受用户的任何输入。使用confirm,如果用户的选择会影响组件的呈现,则可以根据用户单击的内容来设置状态。如果没有,您可以将选择存储为组件成员变量,以备后用。

JimProL2020/03/12 15:07:04

I mean they are more like events than state!

I would not say so. I think loading indicators are a great case of UI that is easily described as a function of state: in this case, of a boolean variable. While this answer is correct, I would like to provide some code to go along with it.

In the async example in Redux repo, reducer updates a field called 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

The component uses connect() from React Redux to subscribe to the store’s state and returns isFetching as part of the mapStateToProps() return value so it is available in the connected component’s props:

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

  return {
    selectedReddit,
    posts,
    isFetching,
    lastUpdated
  }
}

Finally, the component uses isFetching prop in the render() function to render a “Loading...” label (which could conceivably be a spinner instead):

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

Even a worse case, what should I do when I have to use the native confirm dialog or alert dialog in redux/react apps? Where should they be put, actions or reducers?

Any side effects (and showing a dialog is most certainly a side effect) do not belong in reducers. Think of reducers as passive “builders of state”. They don’t really “do” things.

If you wish to show an alert, either do this from a component before dispatching an action, or do this from an action creator. By the time an action is dispatched, it is too late to perform side effects in response to it.

For every rule, there is an exception. Sometimes your side effect logic is so complicated you actually want to couple them either to specific action types or to specific reducers. In this case check out advanced projects like Redux Saga and Redux Loop. Only do this when you are comfortable with vanilla Redux and have a real problem of scattered side effects you’d like to make more manageable.