5

我想在收到来自 api 的带有生成的 url 的成功响应后打开一个 url。我正在尝试像这样在减速器中打开该网址:

window.open(url, '_blank');

对于大多数浏览器来说,这似乎工作正常,但在 safari 中不兼容。

知道如何实现跨浏览器兼容吗?有没有办法用 react-router-redux 做到这一点?

谢谢!

更新:我需要打开一个外部 url,而不是项目中的路由,所以 react-router 可能不是解决方案

4

3 回答 3

5

根据官方 redux 文档,在减速器中你不应该:

  • 改变它的论点;
  • 执行 API 调用和路由转换等副作用;
  • 调用非纯函数,例如 Date.now() 或 Math.random()。

如果您使用redux-thunk中间件发出 api 请求,最好在那里执行重定向。

例如:

// actions.js

function asyncApiCall() {
  return function (dispatch) {
    return fetch('/api')
      .then(response => response.json().then(body => ({ response, body })))
      .then(({ response, body }) => {
        if (response.ok) {
          window.open(url, '_blank');
        }
      });
  };
}
于 2016-07-01T14:16:02.233 回答
3

唯一允许在 Safari/Chrome 中打开新窗口的 javascript 是直接附加到点击处理程序(和其他直接用户输入处理程序)的 javascript。在过去的版本中,人们想出了一些作弊的方法(比如生成一些其他元素——表单或 div——并使用 javascript 模拟用户输入),但新版本更聪明地检测到这一点。

你不应该在减速器中包含这个逻辑。

也许方法是弹出一些模式并提供给用户点击按钮。您可以在收到数据后的操作中执行此操作,通过调度操作类型 {type:"OPEN_MODAL"}

于 2016-07-01T13:34:10.197 回答
3

Reducers 应该是纯的,因此您不应该尝试在那里打开一个新窗口,而是应该为所有 fetch 请求创建一个中间件,然后在成功的请求中您可以重定向、打开 modals 和任何您需要的东西,例如:

import { push } from 'react-router-redux';

export default fetchMiddleware() {
 return ({ dispatch, getState }) => next => action => {
   if (!action.fetch) {
     return next(action);
   }

   const promise = fetch(action.fetch, { someOptionsHere })
     .then(response => response.json())
     .then(data => {
       if (whateverLogicYouNeedToRedirect) {
          return next(push('/go/somewhere/else'));
       }
       next({type: action.type, response: data});
     })
     .catch( error => {
        // check for errors in the response and
        // maybe redirect to login here
        next({type: 'FETCH_FAIL', error });
     });

   return promise;
 };
}

这是一个简单的中间件,它从您的 API 获取数据,然后解析 JSON 响应,然后根据您的逻辑,它可以重定向到不同的 URL 或仅返回带有获取响应的操作,您可以像这样使用操作创建者的这个中间件:

 export function loadData() {
   return {
     type: 'LOAD_SOMETHING',
     fetch: '/api/something/here',
   };
 }

您应该改进中间件以接受参数,一种定义post, put,delete请求的方法以及您需要的任何其他内容,但我希望这能给您一个想法。

于 2016-07-01T14:01:16.830 回答