我想在收到来自 api 的带有生成的 url 的成功响应后打开一个 url。我正在尝试像这样在减速器中打开该网址:
window.open(url, '_blank');
对于大多数浏览器来说,这似乎工作正常,但在 safari 中不兼容。
知道如何实现跨浏览器兼容吗?有没有办法用 react-router-redux 做到这一点?
谢谢!
更新:我需要打开一个外部 url,而不是项目中的路由,所以 react-router 可能不是解决方案
我想在收到来自 api 的带有生成的 url 的成功响应后打开一个 url。我正在尝试像这样在减速器中打开该网址:
window.open(url, '_blank');
对于大多数浏览器来说,这似乎工作正常,但在 safari 中不兼容。
知道如何实现跨浏览器兼容吗?有没有办法用 react-router-redux 做到这一点?
谢谢!
更新:我需要打开一个外部 url,而不是项目中的路由,所以 react-router 可能不是解决方案
根据官方 redux 文档,在减速器中你不应该:
如果您使用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');
}
});
};
}
唯一允许在 Safari/Chrome 中打开新窗口的 javascript 是直接附加到点击处理程序(和其他直接用户输入处理程序)的 javascript。在过去的版本中,人们想出了一些作弊的方法(比如生成一些其他元素——表单或 div——并使用 javascript 模拟用户输入),但新版本更聪明地检测到这一点。
你不应该在减速器中包含这个逻辑。
也许方法是弹出一些模式并提供给用户点击按钮。您可以在收到数据后的操作中执行此操作,通过调度操作类型 {type:"OPEN_MODAL"}
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
请求的方法以及您需要的任何其他内容,但我希望这能给您一个想法。