I’m building a Shopify Remix app and am having trouble getting navigation to work when using the useNavigate() Remix hook. I have two Polaris components attempting to use the hook in the code below (the EmptyState and Page components) and when I click their respective buttons in the UI, nothing happens. I’ve tried adding console.logs within the onAction functions and nothing is showing up in the console either when I click. Does anyone have any ideas?
import {
Card,
Layout,
Page,
Text,
IndexTable,
Thumbnail,
useIndexResourceState,
Badge,
EmptyState,
} from "@shopify/polaris";
import { useLoaderData, useNavigate, Link } from "@remix-run/react";
import { json } from "@remix-run/node";
import { authenticate } from "~/shopify.server";
import { DeleteIcon } from "@shopify/polaris-icons";
import { QUERY_PAGES } from "~/graphql/queries/AdminQueries";
import { request as graphqlRequest } from "graphql-request"
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
dayjs.extend(utc);
export async function loader({ request }) {
await authenticate.admin(request);
const response = await graphqlRequest(process.env.APP_GRAPHQL_URI, QUERY_PAGES);
const pageLayouts = response.GetPages;
return json({ pageLayouts });
}
export default function Pages() {
const { pageLayouts } = useLoaderData();
const navigate = useNavigate();
function getBadgeTone(status: String) {
switch (status) {
case 'Active':
return 'success';
case 'Expired':
return 'critical';
case 'Disabled':
return 'default';
case 'Draft':
return 'attention'
default:
return 'default';
}
}
const resourceName = {
singular: 'pageLayout',
plural: 'pageLayouts',
};
const {selectedResources, allResourcesSelected, handleSelectionChange} =
useIndexResourceState(pageLayouts);
const rowMarkup = pageLayouts.map(
(
{internalId, preview, name, keywords, isDated, category, createdAt, updatedAt, status},
index,
) => (
<IndexTable.Row
id={internalId}
key={internalId}
selected={selectedResources.includes(internalId)}
position={index}
>
<IndexTable.Cell>
<Text variant="bodyMd" fontWeight="bold" as="span">
{internalId}
</Text>
</IndexTable.Cell>
<IndexTable.Cell><Thumbnail source={preview} alt="thumbnail"/></IndexTable.Cell>
<IndexTable.Cell><Link to="url">{name}</Link></IndexTable.Cell>
<IndexTable.Cell>{keywords.join(', ')}</IndexTable.Cell>
<IndexTable.Cell>{isDated ? "Dated" : "Undated"}</IndexTable.Cell>
<IndexTable.Cell>{category.name}</IndexTable.Cell>
<IndexTable.Cell><Badge tone={getBadgeTone(status)}>{status}</Badge></IndexTable.Cell>
<IndexTable.Cell>{dayjs(createdAt).format('DD/MM/YY h:mmA')}</IndexTable.Cell>
<IndexTable.Cell>{dayjs(updatedAt).format('DD/MM/YY h:mmA')}</IndexTable.Cell>
</IndexTable.Row>
),
);
const promotedBulkActions = [
{
icon: DeleteIcon,
destructive: true,
content: 'Delete pages',
onAction: () => console.log('Todo: implement deleting customers'),
},
];
const EmptyLayoutState = () => (
<EmptyState
heading="Add page layouts for customisable planners."
action={{
content: "Add Layout",
onAction: () => {
console.log("Navigate to new page");
navigate('/app/pages/new')
}
}}
image="https://cdn.shopify.com/s/files/1/0262/4071/2726/files/emptystate-files.png"
>
</EmptyState>
);
return (
<Page
fullWidth={true}
title="Page Layouts"
subtitle="test subtitle"
primaryAction={{
content: 'Add Layout',
onAction: () => {
console.log("Navigate to new page");
navigate('/app/pages/new')
}
}
}
>
<Layout>
<Layout.Section>
<Card>
{pageLayouts.length === 0 ? (
<EmptyLayoutState/>
) : (
<IndexTable
resourceName={resourceName}
itemCount={pageLayouts.length}
selectedItemsCount={
allResourcesSelected ? 'All' : selectedResources.length
}
promotedBulkActions={promotedBulkActions}
onSelectionChange={handleSelectionChange}
headings={[
{title: 'ID'},
{title: 'Preview'},
{title: 'Page name'},
{title: 'Keywords'},
{title: 'Dated / Undated'},
{title: 'Category'},
{title: 'Status'},
{title: 'Date Added'},
{title: 'Date Modified'},
]}>
{rowMarkup}
</IndexTable>
)}
</Card>
</Layout.Section>
</Layout>
</Page>
);
}
Katy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.