这是我正在处理的:
- 使用
react
+react-router-dom
构建的单页应用 - 用户点击
<Link to={"/new-page-route"}/>
- URL 更改,我的
<Route/>
开始呈现新<Component/>
我的意思是,React 很快,但我的新组件需要一段时间才能渲染,因为它是一个全新的页面。所以它应该需要 200 到 400 毫秒。如果我没有得到 UI 反馈,感觉我的点击不起作用。
我需要某种 UI 反馈,以便我的用户知道他们的点击已被触发并且正在发生某些事情。我认为我不需要加载器或任何东西,而是表明点击已被 UI "接受"的东西。
理论上,CSS可以使用以下方法进行处理:
-webkit-tap-highlight-color: #SOMECOLOR
active: #SOMECOLOR
但不知何故,当URL更改并开始新的渲染时,浏览器无法将这些CSS结果绘制到屏幕上,至少这是Chrome和Firefox上的行为。这有点奇怪,有时我看到tap-highlight
和active-change
,但几乎总是我看不到它。
注意:这不是移动设备上等待双击的 300 毫秒默认延迟。我已经使用适当的标签处理了这个问题。
我想做的是:
- 停止使用
<Link/>
组件并使用普通<a/>
。 - 创建要在
click
事件后更新的clicked
状态 - 调用
event.preventDefault()
以防止<a/>
导航的正常行为 - 使用
clicked
状态为 UI 反馈呈现一些新样式 clicked
状态变为现实后useEffect
上的火history.push("/new-page-route")
像这样:
const newUrl = "/new-page-route";
const [clicked,setClicked] = useState(false);
const history = useHistory(); // HOOK FROM react-router-dom
function handleLinkClick(event) {
event.preventDefault();
setClicked(true);
}
useEffect(() => {
if (clicked === true) {
history.push(newUrl);
// OR MAYBE ADD A TIMEOUT TO BE EXTRA SURE THAT THE FEEDBACK WILL BE PAINTED
// BECAUSE I'VE SEEN THE BROWSER NOT BEING ABLE TO PAINT IF I DON'T GIVE IT SOME EXTRA TIME
setTimeout(() => history.push(newUrl),100);
}
},[clicked,history]);
// USE THE clicked STATE TO RENDER THE UI FEEDBACK (CHANGE TEXT COLOR, WHATEVER I NEED);
问题
以前有人遇到过这个问题吗?解决这个问题的好方法是什么?我想理论上浏览器应该能够在新渲染开始之前进行绘制,但这不是我得到的。
有问题的沙盒
https://codesandbox.io/s/nice-monad-4fwoc <=== 点击这里查看代码
https://4fwoc.csb.app <=== 单击此处仅查看结果
- 在桌面上:单击链接时,我能够看到
active
状态的BLUE
背景 - 在移动设备上:点击链接时,我没有看到任何 CSS 更改。除非我点击并按住
- 注释:假设您的组件需要一段时间才能渲染。没有任何 UI 反馈,感觉您根本没有单击,即使它在后台呈现也是如此。
import React from "react";
import { Link, Switch, Route } from "react-router-dom";
import styled from "styled-components";
import "./styles.css";
const HOME = "/";
const ROUTE1 = "/route1";
const ROUTE2 = "/route2";
const LS = {};
// REGULAR CSS RULES FOR THE className="link" ARE ON "./styles.css"
LS.Link_LINK = styled(Link)`
color: black;
-webkit-tap-highlight-color: red;
&:active {
background-color: blue;
}
`;
export default function App() {
return (
<React.Fragment>
<div>
<Switch>
<Route exact path={HOME} component={Home} />
<Route exact path={ROUTE1} component={Component1} />
<Route exact path={ROUTE2} component={Component2} />
</Switch>
</div>
</React.Fragment>
);
}
function Home() {
return (
<React.Fragment>
<div>I am Home</div>
<LS.Link_LINK to={ROUTE1}>Route 1 (using styled-components)</LS.Link_LINK>
<br />
<Link className={"link"} to={ROUTE1}>
Route 1 (using regular CSS)
</Link>
</React.Fragment>
);
}
function Component1() {
return (
<React.Fragment>
<div>I am Component1</div>
<LS.Link_LINK to={ROUTE2}>Route 2 (using styled-components)</LS.Link_LINK>
<br />
<Link className={"link"} to={ROUTE2}>
Route 2 (using regular CSS)
</Link>
</React.Fragment>
);
}
function Component2() {
return (
<React.Fragment>
<div>I am Component2</div>
<LS.Link_LINK to={HOME}>Home (using styled-components)</LS.Link_LINK>
<br />
<Link className={"link"} to={HOME}>
Home (using regular CSS)
</Link>
</React.Fragment>
);
}
您应该使用两个loading
阶段。
- 使用懒惰 装载 加载"繁重"页面并显示 骨架 组件作为回退,向用户显示某些内容正在加载。
- 使用组件/redux 状态加载指示器来表示您的页面何时 从 API 加载数据
试图通过 react-router 链接来实现这一点并不是最好的方法,因为路由会立即发生,它不是阻碍应用程序的原因。API 调用和多次重新呈现会导致应用程序运行缓慢。