Questions and discussions about using the Shopify CLI and Shopify-built libraries.
Hey everyone,
I've been setting up the ui-nav-menu component (as shown below) on my embedded app and have it all up and running using react-router-dom routes and links:
<ui-nav-menu>
<Link to="/" rel="home">Home</Link>
<Link to="/manage-blogs">Manage Blogs</Link>
<Link to="/manage-inputs">Manage Inputs</Link>
<Link to="/manage-plans">Manage Plans</Link>
</ui-nav-menu>
<ClientRouter history={history} />
<Routes>
<Route exact path="/" element={DashboardComponent} />
<Route exact path="/dashboard" element={DashboardComponent} />
etc...
My one remaining issue is that when I refresh or reload the Shopify page, it loads the correct section based on the URL, but the 'active link' in the side panel no longer changes when I click a new link. Navigation works fine; it's purely the active styling that flickers to my newly clicked link and then back to the original one that was selected when I refreshed. Everything works as expected before refreshing.
Has anyone encountered this issue before? Could there be something simple I am missing?
Thanks in advance for your help.
autoBlogger: Seamlessly scheduled, fully automated, AI-powered, and SEO-optimised blogging with a host of free extras! Start your 14-day free trial today!
Hi Olllie,
It seems like the issue might be related to the state not being properly updated on page refresh. When you refresh the page, the app might be using the initial state, which is causing the 'active link' to default back to the original one.
One solution might be to leverage the use of useEffect()
and useState()
hooks in React. You can use useState()
to create a state variable for the active link and useEffect()
to update this state variable whenever the URL path changes.
Here's an example:
import React, { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
//...other imports
const MyComponent = () => {
const location = useLocation();
const [activeLink, setActiveLink] = useState('/');
useEffect(() => {
setActiveLink(location.pathname);
}, [location]);
return (
<ui-nav-menu>
<Link to="/" rel="home" className={activeLink === '/' ? 'active' : ''}>Home</Link>
<Link to="/manage-blogs" className={activeLink === '/manage-blogs' ? 'active' : ''}>Manage Blogs</Link>
//...other links
</ui-nav-menu>
);
};
In this example, useLocation()
is a hook from react-router-dom
that returns the current location object which contains the current URL path. useEffect()
is used to update the activeLink
state variable every time the URL path changes. The className
property is then set conditionally based on whether or not the link's path matches the current URL path.
Remember to add appropriate styles for the 'active' class in your CSS to highlight the active link.
Hope this helps! If the problem persists, please provide more details about your setup.
Liam | Developer Advocate @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
Hi @Liam , I think the issue here is with how App Bridge is handling the current URL:
https://shopify.dev/docs/api/app-bridge-library/reference/navigation-menu
Since it's within the `<ui-nav-menu>` component it should have the active state set by App Bridge. I'm also having this issue though, where App Bridge will randomly decide which link is currently active.
@Olllie I've had some better luck replacing the `<Link />` element from my framework with a plain ol' `<a>`
For anyone who still has this issue with <ui-nav-menu> not updating when the route is changing the hack would be to useState and temorary change it to fix.
....
const [isChanging, setIsChanging] = useState(false);
const handleChange = useCallback((route) => {
navigate(route);
setIsChanging(true);
setTimeout(() => setIsChanging(false), 100);
}, []);
const navMarkup = <ui-nav-menu>
<Link to="/" rel="home">Home</Link>
<Link to="/manage-blogs">Manage Blogs</Link>
<Link to="/manage-inputs">Manage Inputs</Link>
<Link to="/manage-plans">Manage Plans</Link>
</ui-nav-menu>
return (
<>
{isChanging ? navMarkup : navMarkup}
.......
Could you share the whole example!? Where is the handleChange used?
you can use the handleChange() anywhere you want to handle navigation like a button or a link! The above issue only occurs when you do not navigate using the ui-nav-menu.
<Button onClick={handleChange} >more</Button>
Another solution using hooks:
import { NavMenu } from "@shopify/app-bridge-react";
import { useMemo } from "react";
import { useLocation, Link } from "react-router-dom";
const location = useLocation();
const navMenu = useMemo(() =>
<NavMenu key={location.key}>
<Link to="/" rel="home">Home</Link>
<Link to="/manage-blogs">Manage Blogs</Link>
<Link to="/manage-inputs">Manage Inputs</Link>
<Link to="/manage-plans">Manage Plans</Link>
</NavMenu>, [location]);
{ navMenu }
You can later use the Link component from Polaris like this:
import { useNavigate } from "react-router-dom";
import { Link } from "@shopify/polaris";
const navigate = useNavigate();
<Link onClick={() => navigate(`/manage-blogs`)}>Manage Blogs</Link>
The navigation menu shows the correct page when you use both the left menu and the component navigation.