My current challenge involves:
- Developing a single-page application using
react
andreact-router-dom
- When a user clicks on a
, the URL changes and a new<Link to={"/new-page-route"}/>
<Component/>
starts rendering
While React is fast, my new component takes a bit of time to render as it's a whole new page. This process usually takes between 200 and 400ms. If there is no UI feedback during this time, it might feel like the click didn't register.
I want to provide some form of UI feedback to indicate to users that their click has been recognized and something is happening in the background. I'm not looking for loaders specifically, but rather something subtle to signify that the click has been acknowledged by the UI.
In theory, CSS can handle this through:
-webkit-tap-highlight-color: #SOMECOLOR
active: #SOMECOLOR
However, when the URL changes and the new render begins, the browser seems unable to display these CSS results on the screen consistently. This behavior is noticeable in Chrome and Firefox where sometimes the effects are visible, but often they are not.
NOTE: This issue is distinct from the 300ms default delay on mobile devices related to double-tapping, which I've addressed using appropriate tags.
One potential solution I am considering involves:
- Replacing the
<Link/>
component with a regular<a/>
tag - Creating a
clicked
state to be updated after theclick
event - Using
event.preventDefault()
to prevent the default navigation behavior of the<a/>
tag - Utilizing the
clicked
state to apply new styles for UI feedback - Triggering
history.push("/new-page-route")
within auseEffect
once theclicked
state is true
This approach might look something like this:
// Code snippet demonstrating the suggested approach
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);
setTimeout(() => history.push(newUrl),100); // Optionally add a timeout for better assurance of UI feedback
}
},[clicked,history]);
// Use the clicked state to render the desired UI feedback;
QUESTION
Has anyone encountered similar issues before? What effective methods have you used to address this? The expectation is that the browser should reflect UI changes before initiating the new render, but this doesn't seem to be happening in practice.
SANDBOX WITH THE ISSUE
Explore the sandbox to view the code
View the result only here
- Desktop Experience: The active state background turns
BLUE
upon clicking the link - Mobile Experience: No CSS changes are observed when clicking links unless tapped and held
- Insights: When components take a while to render without any UI feedback, it may appear as though the click was ineffective, despite ongoing rendering processes.
// Sample code snippets illustrating component structure, styling, and routing logic.
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 = {};
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>
);
}
// Separate functions/components for Home, Component1, and Component2 omitted for brevity