【问题标题】:How to cancel ajax when route changing using react router使用反应路由器更改路由时如何取消ajax
【发布时间】:2017-07-22 21:05:51
【问题描述】:
 export const getSomethingEpic = action$ =>
  action$
    .ofType(GET_SOMETHING)
    .switchMap(action =>
      ajax('url/api/something')
        .map((json) => {
          return getSomethingEndAct(json.response);
        })
        .takeUntil(action$.ofType('@@router/LOCATION_CHANGE'))
    );

情况是这样的:

页面 A 有一个反应路由器链接到页面 B,在页面 B 上 componentDidMount 我调度 getSomething 操作。 Ajax 可以完美取消。但是,如果页面 B 加载完成,ajax 完成,我们从页面 B 路由到页面 C,然后使用浏览器返回按钮再次路由到页面 B,action getSomething 将再次在 componentDidMount 中调度,但这次 ajax 被取消.

我不明白为什么要取消 ajax,因为位置更改是在 getSomething 操作之前。 或者当路由改变时我应该怎么做才能取消ajax?

我尝试构建一个示例,但我无法让 react-router-redux 同步浏览器历史记录。这是http://jsbin.com/dewixurece/edit?js,console,output 如果使用 hashHistory,它会起作用,但是会有两个位置更改操作,应该是一个,我不知道为什么。

这是一个很棒的库,我真的很喜欢 RX 编程理念,但仍在学习并希望我们能有更多的例子。如果有人可以提供帮助,谢谢。

【问题讨论】:

  • 很难理解是什么问题?听起来你说你想离开时取消,但又不想离开时取消,这是矛盾的。能改一下吗?
  • 对不起,说清楚:我希望在离开页面 B 时取消它,但如果我使用浏览器导航按钮从页面 C 返回页面 B,它实际上取消了。当我导航回到 (返回)页面 B,ajax 操作已调度并取消,我不希望这样。
  • 嗯,很难说没有看到一个工作的例子。我注意到您正在使用switchMap,这意味着如果您有一个待处理的ajax('url/api/something')另一个 GET_SOMETHING 操作,它将取消待处理的操作并开始一个新操作。不知道你是不是这个意思?你能创建一个 JSBin 来演示这个问题吗? jsbin.com/zomire/edit?js,output
  • 谢谢@jayphelps 我已经根据你的 react-router-redux 做了一个示例,但它在 jsbin 中无法正常工作。也许你能给我一个当用户改变路由时取消 ajax 的例子。我的方法是监听动作类型是否为 LOCATION_CHANGE,即 react-router-redux 的动作。

标签: react-router rxjs rxjs5 react-router-redux redux-observable


【解决方案1】:

(基于我们在 cmets 中的讨论)

如果您想在输入路由时开始请求,但如果您在完成之前离开该路由则取消它,您将在componentDidMount 中分派开始操作,在componentWillUnmount 中分派取消操作

const getSomethingEpic = action$ =>
  action$.ofType('GET_SOMETHING')
    .switchMap(action =>
      ajax('url/api/something')
        .map((json) => {
          return getSomethingEndAct(json.response);
        })
        .takeUntil(action$.ofType('GET_SOMETHING_CANCELLED'))
    );

class B extends Component {
  componentDidMount() {
    store.dispatch({
      type: 'GET_SOMETHING'
    });
  }

  componentWillUnmount() {
    store.dispatch({
      type: 'GET_SOMETHING_CANCELLED'
    });
  }

  render() {
    return (
      <h1>B route</h1>
    );
  }
}

演示:http://jsbin.com/zomire/edit?js,output

为了简单起见,我直接使用了store.dispatch。如果您愿意,可以在您的实际应用中使用动作创建者和/或connect()

调度取消操作,即使 ajax 请求已经完成,通常也不是问题——但如果是这样,或者您更愿意只在真正需要时调度它,您将需要存储某种状态您可以使用它来了解请求是否仍处于待处理状态。您可以将此状态存储为本地组件状态或在 redux 存储中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多