React-router 在 transitionTo 上意外重新加载 (Chrome)
React-router unintended reload on transitionTo (Chrome)
在 React 和 React Router 之上实现的(单页)应用程序中,我们在使用 router.transitionTo 方法时观察到一个奇怪的模式。
对于过于冗长的上下文表示歉意,但不想错过一些相关的内容。
假设我们有以下路由器初始化,它是从应用程序的单个 "physical" 页面调用的:
define([], function () {
var _Root = React.createClass({
render : function () {
return React.createElement(React.addons.CSSTransitionGroup, {/**/},
React.createElement(Router.RouteHandler, {/**/}));
}
});
var _NotFoundScreen = React.createClass({/**/});
var _NoDefaultScreen = React.createClass({/**/});
var routes = (
React.createElement(Router.Route, {
handler : _Root,
path : "/SampleApplication/"
},
React.createElement(Router.Route, {
path : "Transfer",
handler : Transfer
}),
React.createElement(Router.Route, {
path : "Home",
handler : Home
}),
React.createElement(Router.DefaultRoute, {
handler : Home || _NoDefaultScreen
}),
React.createElement(Router.NotFoundRoute, {
handler : _NotFoundScreen
})));
return {
init : function () {
var router = Router.create({
routes : routes,
location : Router.HistoryLocation
});
router.run(function (rootClass, state) {
if (state.routes.length === 0) {
window.location = state.path;
}
React.render(React.createElement(rootClass, state), document.getElementById("reactContainer"));
});
}
}
});
然后我们有 "Transfer" 页面,其中包含以下内容:
define([], function () {
var View = (function (_super) {
/*(...)*/
function View() {
/*(...)*/
}
View.prototype.render = function () {
/*(...)*/
return React.DOM.div(null, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn",
visible : true
}, "B1"), React.DOM.br(), "form:", React.createElement(Form.Form, {
style : "form",
visible : true
}, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn btn-primary",
visible : true
}, "B2")));
};
return View;
})(/*(...)*/);
return View;
});
因此,转账 页面上有 2 个按钮 - B1 和 B2。 B2 由 "form" 元素包裹。这两个按钮都可以 "navigating" 单击主页。
通过 B1 的导航按预期工作。
通过 B2 的导航揭示了一些奇怪的行为。
- 浏览器url:host/SampleApplication/Transfer
- 我们点击B2
- 我们 "navigate" 到 host/SampleApplication/Home 并在几分之一秒内查看页面内容
- 几分之一秒后,浏览器 url 更改为 host/SampleApplication/Home?
- 我们得到一个白屏(好像我们是第一次 loading/accessing 应用程序并且它正在初始化)
- 我们得到呈现的页面@host/SampleApplication/Home?
我已经尝试查找问题一段时间了,似乎没有任何调试产生任何结果。
B1 和 B2 的导航执行流程是相同的(一直到 React Router 调用 location.push(path) 的地方)。
此外,这种 "only" 发生在 Chrome(桌面和移动)、Opera(移动)和 Android 股票浏览器上,而对于 Firefox(桌面和移动)B1 和B2 能够从一个页面导航到另一个页面,无需任何额外的重新加载,也不需要 "leaving" 应用程序的单个物理页面。
我一直无法找到任何有关类似行为模式的相关信息来解释可能发生的情况。
如果有人能提供一些关于这里可能发生的事情的见解,我们将不胜感激。
谨致问候,
SYG
好的,问题的根源被确定为按钮元素的默认类型 - 提交 (link HTML 建议)。
由于按钮在表单元素中呈现,按钮的 "onClick" 隐式提交表单,导致页面重新加载排队。按钮的 "onClick" 执行 router.transitionTo,有效地导航到目标页面,然后立即执行从表单提交重新加载的 "queued" 页面,导致应用程序重新初始化。
通过将按钮元素的类型更改为 button,行为是 "fixed"。
在 React 和 React Router 之上实现的(单页)应用程序中,我们在使用 router.transitionTo 方法时观察到一个奇怪的模式。
对于过于冗长的上下文表示歉意,但不想错过一些相关的内容。
假设我们有以下路由器初始化,它是从应用程序的单个 "physical" 页面调用的:
define([], function () {
var _Root = React.createClass({
render : function () {
return React.createElement(React.addons.CSSTransitionGroup, {/**/},
React.createElement(Router.RouteHandler, {/**/}));
}
});
var _NotFoundScreen = React.createClass({/**/});
var _NoDefaultScreen = React.createClass({/**/});
var routes = (
React.createElement(Router.Route, {
handler : _Root,
path : "/SampleApplication/"
},
React.createElement(Router.Route, {
path : "Transfer",
handler : Transfer
}),
React.createElement(Router.Route, {
path : "Home",
handler : Home
}),
React.createElement(Router.DefaultRoute, {
handler : Home || _NoDefaultScreen
}),
React.createElement(Router.NotFoundRoute, {
handler : _NotFoundScreen
})));
return {
init : function () {
var router = Router.create({
routes : routes,
location : Router.HistoryLocation
});
router.run(function (rootClass, state) {
if (state.routes.length === 0) {
window.location = state.path;
}
React.render(React.createElement(rootClass, state), document.getElementById("reactContainer"));
});
}
}
});
然后我们有 "Transfer" 页面,其中包含以下内容:
define([], function () {
var View = (function (_super) {
/*(...)*/
function View() {
/*(...)*/
}
View.prototype.render = function () {
/*(...)*/
return React.DOM.div(null, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn",
visible : true
}, "B1"), React.DOM.br(), "form:", React.createElement(Form.Form, {
style : "form",
visible : true
}, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn btn-primary",
visible : true
}, "B2")));
};
return View;
})(/*(...)*/);
return View;
});
因此,转账 页面上有 2 个按钮 - B1 和 B2。 B2 由 "form" 元素包裹。这两个按钮都可以 "navigating" 单击主页。
通过 B1 的导航按预期工作。
通过 B2 的导航揭示了一些奇怪的行为。
- 浏览器url:host/SampleApplication/Transfer
- 我们点击B2
- 我们 "navigate" 到 host/SampleApplication/Home 并在几分之一秒内查看页面内容
- 几分之一秒后,浏览器 url 更改为 host/SampleApplication/Home?
- 我们得到一个白屏(好像我们是第一次 loading/accessing 应用程序并且它正在初始化)
- 我们得到呈现的页面@host/SampleApplication/Home?
我已经尝试查找问题一段时间了,似乎没有任何调试产生任何结果。
B1 和 B2 的导航执行流程是相同的(一直到 React Router 调用 location.push(path) 的地方)。
此外,这种 "only" 发生在 Chrome(桌面和移动)、Opera(移动)和 Android 股票浏览器上,而对于 Firefox(桌面和移动)B1 和B2 能够从一个页面导航到另一个页面,无需任何额外的重新加载,也不需要 "leaving" 应用程序的单个物理页面。
我一直无法找到任何有关类似行为模式的相关信息来解释可能发生的情况。
如果有人能提供一些关于这里可能发生的事情的见解,我们将不胜感激。
谨致问候,
SYG
好的,问题的根源被确定为按钮元素的默认类型 - 提交 (link HTML 建议)。
由于按钮在表单元素中呈现,按钮的 "onClick" 隐式提交表单,导致页面重新加载排队。按钮的 "onClick" 执行 router.transitionTo,有效地导航到目标页面,然后立即执行从表单提交重新加载的 "queued" 页面,导致应用程序重新初始化。
通过将按钮元素的类型更改为 button,行为是 "fixed"。