Add Delete Functionality in Shopify App with Remix.js and Polaris | Shopify App Development

In the realm of Shopify app development, creating an intuitive and functional user interface is crucial for enhancing the user experience. One of the key features often required in a custom Shopify app is the ability to delete items, whether they are products, orders, or other entities. This article will guide you through adding delete functionality to a Shopify app using Remix.js and Shopify Polaris. By the end of this tutorial, you will understand how to implement this feature, ensuring that your app is both functional and user-friendly.

Why Use Remix.js and Polaris for Shopify App Development?

Before diving into the technical steps, let’s briefly discuss why Remix.js and Shopify Polaris are excellent choices for developing a Shopify app with delete functionality:

  • Remix.js: Remix is a powerful React-based framework that excels in server-side rendering and optimized data loading. It’s ideal for building dynamic, fast, and SEO-friendly web applications, making it a great fit for Shopify app development.
  • Shopify Polaris: Polaris is Shopify’s design system, offering a comprehensive set of React components that ensure your app’s UI is consistent with Shopify’s own interface. Using Polaris components like buttons, modals, and data tables makes it easier to implement features such as deleting items.

Setting Up Your Development Environment

Before implementing delete functionality, you need to set up your development environment. Here’s how:

  1. Install Node.js: Ensure that Node.js and npm (Node Package Manager) are installed on your machine.
  2. Create a Shopify App with Remix.js: Use the Shopify CLI to create a new app with Remix.js as the frontend framework:bashCopy codeshopify app create node -t remix This command sets up a new Shopify app with Remix.js, preparing the foundation for our delete functionality.
  3. Install Shopify Polaris: Navigate to your app’s directory and install Polaris components:bashCopy codenpm install @shopify/polaris
  4. Set Up Remix.js: Ensure that your Remix.js environment is properly configured, including setting up routes, loaders, and actions for handling data and user interactions.

Fetching and Displaying Data

To add delete functionality, we first need to fetch and display the items that can be deleted. For this tutorial, let’s assume we are working with Shopify products.

Step 1: Fetch Products from Shopify API

Create a utility function to fetch products from the Shopify API. In your utils directory, create a file named fetchProducts.js:

javascriptCopy codeimport { gql } from 'graphql-request';
import { shopifyClient } from './shopifyClient';

export async function fetchProducts() {
  const query = gql`
    {
      products(first: 10) {
        edges {
          node {
            id
            title
            handle
          }
        }
      }
    }
  `;

  const response = await shopifyClient.request(query);
  return response.products.edges.map(edge => edge.node);
}

This function uses GraphQL to retrieve the first 10 products from your Shopify store.

Step 2: Display Products Using Polaris DataTable

Create a new component, ProductsPage.jsx, to display the fetched products in a table. Use the Polaris DataTable component to list the products:

javascriptCopy codeimport { Page, Card, DataTable, Button } from '@shopify/polaris';
import { useLoaderData } from '@remix-run/react';
import { fetchProducts } from '../utils/fetchProducts';

export async function loader() {
  const products = await fetchProducts();
  return products;
}

function ProductsPage() {
  const products = useLoaderData();

  const rows = products.map(product => [
    product.title,
    product.handle,
    <Button destructive onClick={() => handleDelete(product.id)}>Delete</Button>
  ]);

  return (
    <Page title="Products">
      <Card>
        <DataTable
          columnContentTypes={['text', 'text', 'text']}
          headings={['Title', 'Handle', 'Actions']}
          rows={rows}
        />
      </Card>
    </Page>
  );
}

export default ProductsPage;

In this code:

  • DataTable Component: The DataTable component from Polaris displays the product data in a table format. Each row includes a title, handle, and a delete button.
  • Delete Button: A Button component is added to each row, with a destructive style to indicate the delete action.

Implementing Delete Functionality

Next, we’ll implement the functionality to delete a product when the delete button is clicked.

Step 1: Create the Delete Function

In the same ProductsPage.jsx file, add the handleDelete function:

javascriptCopy codeimport { useFetcher } from '@remix-run/react';

function ProductsPage() {
  const products = useLoaderData();
  const fetcher = useFetcher();

  const handleDelete = (productId) => {
    fetcher.submit(
      { productId },
      { method: 'post', action: '/products/delete' }
    );
  };

  const rows = products.map(product => [
    product.title,
    product.handle,
    <Button destructive onClick={() => handleDelete(product.id)}>Delete</Button>
  ]);

  return (
    <Page title="Products">
      <Card>
        <DataTable
          columnContentTypes={['text', 'text', 'text']}
          headings={['Title', 'Handle', 'Actions']}
          rows={rows}
        />
      </Card>
    </Page>
  );
}

The handleDelete function triggers a POST request to the /products/delete action, passing the product ID that needs to be deleted.

Step 2: Create the Delete Action

Now, create the action that handles the deletion. In your routes directory, create a file named products.delete.js:

javascriptCopy codeimport { redirect } from '@remix-run/node';
import { shopifyClient } from '../../utils/shopifyClient';
import { gql } from 'graphql-request';

export async function action({ request }) {
  const formData = await request.formData();
  const productId = formData.get('productId');

  const mutation = gql`
    mutation DeleteProduct($id: ID!) {
      productDelete(input: { id: $id }) {
        deletedProductId
      }
    }
  `;

  await shopifyClient.request(mutation, { id: productId });

  return redirect('/products');
}

This action performs the following steps:

  • Receive the Product ID: It receives the product ID from the form data.
  • Delete the Product: It uses a GraphQL mutation to delete the specified product from Shopify.
  • Redirect: After deletion, the user is redirected back to the products page.

Enhancing User Experience

To provide a better user experience, consider adding the following enhancements:

  1. Confirmation Dialog: Before deleting a product, show a confirmation dialog to ensure the user wants to proceed with the deletion.
  2. Loading States: Indicate when the deletion is in progress by showing a loading state or disabling the delete button temporarily.
  3. Error Handling: Handle errors gracefully by showing an error message if the deletion fails.

Here’s an example of adding a confirmation dialog using Polaris:

javascriptCopy codeimport { useState } from 'react';
import { Modal } from '@shopify/polaris';

function ProductsPage() {
  const [active, setActive] = useState(false);
  const [productToDelete, setProductToDelete] = useState(null);
  const products = useLoaderData();
  const fetcher = useFetcher();

  const toggleModal = () => setActive(!active);

  const handleDelete = (productId) => {
    setProductToDelete(productId);
    toggleModal();
  };

  const confirmDelete = () => {
    fetcher.submit(
      { productId: productToDelete },
      { method: 'post', action: '/products/delete' }
    );
    toggleModal();
  };

  const rows = products.map(product => [
    product.title,
    product.handle,
    <Button destructive onClick={() => handleDelete(product.id)}>Delete</Button>
  ]);

  return (
    <Page title="Products">
      <Card>
        <DataTable
          columnContentTypes={['text', 'text', 'text']}
          headings={['Title', 'Handle', 'Actions']}
          rows={rows}
        />
      </Card>

      <Modal
        open={active}
        onClose={toggleModal}
        title="Delete Product"
        primaryAction={{
          content: 'Delete',
          destructive: true,
          onAction: confirmDelete,
        }}
        secondaryActions={[
          {
            content: 'Cancel',
            onAction: toggleModal,
          },
        ]}
      >
        <Modal.Section>
          <p>Are you sure you want to delete this product?</p>
        </Modal.Section>
      </Modal>
    </Page>
  );
}

Testing and Deployment

After implementing the delete functionality, thoroughly test it:

  • Delete Functionality: Ensure that products are correctly deleted from your Shopify store.
  • Error Scenarios: Test how the app handles scenarios like network failures or invalid product IDs.
  • User Experience: Ensure the UI is responsive, with appropriate feedback for users during the deletion process.

Once testing is complete, deploy your Shopify app using the Shopify CLI:

bashCopy codeshopify app deploy

Conclusion

Adding delete functionality to your Shopify app using Remix.js and Polaris is a key feature that enhances the usability of your application. By following this tutorial, you’ve learned how to fetch data from the Shopify API, display it using Polaris components,

Leave a Reply

Your email address will not be published. Required fields are marked *