What do users think of the UI feedback when they click on a react-router-dom <Link/> component?

My current challenge involves:

  • Developing a single-page application using react and react-router-dom
  • When a user clicks on a
    <Link to={"/new-page-route"}/>
    , the URL changes and a new <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 the click 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 a useEffect once the clicked 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

Answer №1

Implementing two loading phases is recommended for optimal performance.

  1. For "heavy" pages, utilize lazy loading along with a skeleton component as a placeholder to indicate progress to the user.
  2. When fetching data from APIs, consider using a loading indicator in your component or Redux state.

It's important to note that relying on react-router links for this purpose may not be effective, as routing happens instantly and does not significantly impact application performance. Slowdowns are typically caused by API calls and frequent re-renders.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Toggle button to collapse the Bootstrap side bar on larger screens

I am currently utilizing the following template: An issue I am facing is that I want my sidebar to either shrink or hide when a button is clicked, specifically on a 22" PC screen. I have experimented with several solutions without achieving success. Alt ...

Learn how to set up webpack or Next.js to generate a CSS file from custom Material styles and automatically inject it into the header

One of the things I've done is define some custom material styles, like this: import {createStyles, makeStyles, Theme} from '@material-ui/core/styles'; export const useStyles = makeStyles((theme: Theme) => createStyles({ fab ...

What is the best way to save a webpage when a user clicks a button before leaving the page with Javascript

I've exhausted all my options in trying to find a way to trigger a button that saves the page upon exit, but it never seems to work. I need the event to occur even if the button is not visible at the time of the page exit. The new security protocols o ...

I'm looking for a solution to enable the execution of 'expandRowByClick' only when clicking on a specific area within the row in Ant Design. Any suggestions?

In my quest to create a expandable table row with Ant Design's built-in expandRowByClick function, I encountered a dilemma. The function allows me to expand a row by clicking anywhere in it, but what if I want this feature to apply only to a specific ...

Click on the text next to my checkbox to activate it

I've been attempting to create a situation where the text next to my checkbox is clickable. However, for some reason, the code I'm using doesn't seem to be working as expected. Can anyone help me troubleshoot this issue? <form name="f1"& ...

Potential dangers involved in sending HTML content through an AJAX request over a secure HTTPS connection

I am exploring the idea of dynamically loading HTML content, such as updating a Bootstrap modal dialog's contents using AJAX calls instead of refreshing the entire page. However, before I proceed, I want to understand the potential risks involved and ...

Ensuring the mobile menu button is always visible on Bootstrap 4, regardless of screen size

Is there a way to consistently display the mobile menu button regardless of screen size? I want the links to only appear when someone clicks on the mobile button. Thank you! I am aware of a solution for Bootstrap 3, but it does not seem to work with Boots ...

Why is it that the social media anchors on my React web application are not functioning correctly, and mysteriously only work when the user reloads the page?

Whenever a user clicks on it, the anchor link does not open anything. However, after reloading the browser, the anchor link successfully opens the social media URL. The issue arises when the user navigates to another page and then returns to the Contact pa ...

What benefits does utilizing unordered lists provide in navigation bars?

Throughout my research, I have come across numerous tutorials detailing the process of creating a navigation bar. They often begin by adding an unordered list and then proceed to remove the default styling such as bullet points and margins from both the ...

Loading a local image using Jquery in an open dialog

Hello to all fellow stackoverflow users! I am currently facing an issue while trying to load a local jpeg file into a dialog box. The problem is that no matter what, the same table information keeps getting appended and reopened in the dialog box. I must h ...

Eliminating inline JavaScript code

Hello everyone, I need some help with my website. I have a series of image comparisons and I've currently used inline JS to manage them. However, as the number of comparisons has increased, I realize that inline JS is not the best solution for this. C ...

Using axios-mock-adapter to mock onGet requests does not always yield the desired results

I've been testing axios calls with axios-mock-adapter and ran into an unexpected issue: During my tests, the API calls always return real data instead of the mocked data I set up using mock.onGet. It seems like the receivedActions are coming from the ...

Error message during Jest Enzyme testing: The "store" was not located within the scope of "Connect(App)"

I am faced with an issue in my index.js file, which includes: import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App' import * as serviceWorker from './servi ...

I'm struggling to get this if statement to function properly in my JavaScript code - can anyone help? :)

I have encountered an issue with two functions that are meant to retrieve the user_id of a user. One function obtains the session user_id, while the other retrieves the id from the URL like this: profile.html?id=123. Below is the code snippet: // Extracti ...

Deactivate a table row when a different one is selected

Is there a way to disable other rows in a react material-table when one row is selected? I have set the selection to true using the following code: material-table selection: true I tried using "onSelectionChange" but couldn't get it to work for my s ...

JavaScript's Automated Retail Machine Feature

I'm still in the early stages of learning Javascript, having dabbled with it for a couple of weeks. This marks my first time posting, so I apologize if my explanation is not comprehensive enough, but I'll do my best! My goal is to create a funct ...

What could be the reason for the onmessage listener not handling the initial SSE event?

When a client connects to a Node Express server, it creates a new EventSource. The server sends an SSE event upon initial connection and then at a 30-second interval thereafter. Strangely, the client's onmessage handler does not respond to the initial ...

What is the key to ensuring the content in your canvas adapts to different screen sizes

Greetings! I wanted to extract the values from this specific meta tag: <meta name="viewport" property="viewport" content="width-device-width, initial-scale=1"> To retrieve content from a meta tag using JavaScript, I used the following code snippet: ...

Ways to extract data from form inputs with the help of jQuery

My HTML form allows users to enter data and upon submission, I need to use jQuery to capture the entered values. <form class="my-form needs-validation" method="POST"> <input type="text" id="firstName" name="First Name"> <input type="tex ...

What could be causing my router UI in angular.js to malfunction?

Having an issue with routing not functioning as intended, here is the relevant code: $urlRouterProvider. otherwise('/list'); $stateProvider. state('home', { abstract: true, views: { 'header': { templateUrl: &apos ...