1

I'm very new to Polaris/Shopify and need some help with a problem.

I'm using <IndexTable /> to create a list of offers for our store, which uses promotedBulkActions.

These are all working fine and the API calls are happening as expected. My problem is that I need to make the content dynamic. For example, if a user deletes an entry I'd like the row to disappear or if they toggle the state of an entry, I'd like to see the status change automagically.

I got the original information from:

https://polaris.shopify.com/components/index-table

...which has worked fine, but it's only using static data.

The data itself is called from a custom API endpoint then parsed into a variable rowMarkup. I think it should have something to do with useState but I'm just struggling with the last bit.

My current code (with the unimportant bits removed) is:

import {
    Card,
    IndexTable,
    useIndexResourceState,
    Filters,
    TextField
} from "@shopify/polaris";

import { useAppQuery, useAuthenticatedFetch } from "../hooks";
import { useState, useCallback } from 'react';
import { useEffect, useLayoutEffect } from "react";
import { TitleBar, useNavigate } from "@shopify/app-bridge-react";
import { data } from "@shopify/app-bridge/actions/Modal";



export function OfferTabs() {
    const [offers, setOffers] = useState([]);
    const [taggedWith, setTaggedWith] = useState('current');
    const [offerList, setOfferList] = useState([]);
    const [selected, setSelected] = useState(0);
    const [active, setActive] = useState(false);
    const [statusText, setStatusText] = useState('Active');
    const [status, setStatus] = useState(1);
    const navigate = useNavigate();


    useLayoutEffect(() => {
        fetch("xxxxx")
            .then(res => res.json())
            .then(result => {
               
                setOffers(result);
                
            });
    }, []);

    // const fetch = useAuthenticatedFetch();





    const getStatusText = (status) => {
        const _t = (status === 1) ? 'Active' : 'Inactive';
        //  setStatus(_t);
        return _t;
    }

    const getContent = (type) => {
        let _return = [];
        Object.keys(offers).map(o => {
            offers[o].map(m => {
                _return.push(
                    {
                        id: m.id,
                        name: m.name,
                        type: m.type,
                        start_date: m.start_date,
                        end_date: m.end_date,
                        status: m.status,
                        status_text: getStatusText(m.status),
                        shopify_id: m.shopify_id,
                        offer_type: o
                    }
                );
            });
        });
        
        return _return;
    }

    /* handling functions */

    const handleDelete = () => {

        const _itemCount = selectedResources.length;
        const _qtyStr = (_itemCount === 1) ? "this item" : `these ${_itemCount} items`
        if (confirm(`Do you want to delete ${_qtyStr}?\nThis cannot be undone!`)) {
             const _queryData = selectedResources.join(",");
             const _queryURL = `xxxx`;
             const _headers = {'method':'DELETE'}

            /* send the request and remove the elements from the DOM */

            fetch(_queryURL,_headers)
            .then(()=> {
             console.log("TO DO: Auto-refresh the content");
            });

        
            }



    }


    const handleStatusChange = (v) => {

        const _itemCount = selectedResources.length;
        const _qtyStr = (_itemCount === 1) ? "this item" : `these ${_itemCount} items`
        if (confirm(`Do you want to change the status of ${_qtyStr}?`)) {
            const _queryData = selectedResources.join(",");
            const _queryURL = `https://xxxxx`;
            const _headers = { 'method': 'PUT' }
             fetch(_queryURL,_headers)
             .then(()=> {
                console.log("TO DO: Auto-refresh the content");
            });
        }
    }


    /* this will convert the offers data into the correct format for an IndexTable */

    const indexContent = getContent();
    const resourceName = {
        singular: 'promotion',
        plural: 'promotions',
    };

    const { selectedResources, allResourcesSelected, handleSelectionChange } =
        useIndexResourceState(indexContent);

    const rowMarkup = indexContent.map(
        ({ id, name, type, start_date, end_date, status, status_text, offer_type }, index) => (
            <IndexTable.Row
                id={id}
                key={id}
                selected={selectedResources.includes(id)}
                position={index}
            >
                <IndexTable.Cell>{name}</IndexTable.Cell>
                <IndexTable.Cell>{type}</IndexTable.Cell>
                <IndexTable.Cell>{start_date}</IndexTable.Cell>
                <IndexTable.Cell>{end_date}</IndexTable.Cell>
                <IndexTable.Cell>{offer_type}</IndexTable.Cell>
                <IndexTable.Cell>{status_text}</IndexTable.Cell>
            </IndexTable.Row>
        ),
    );


    const promotedBulkActions = [
        {
            title: "Change Status",
            actions: [
                {
                    content: 'Activate',
                    onAction: () => handleStatusChange(1)
                },
                {
                    content: 'Deactivate',
                    onAction: () => handleStatusChange(0)
                }
            ]
        },
        {
            title: "Other Actions",
            actions: [
                {
                    content: 'Delete',
                    onAction: handleDelete
                }
            ]
        }
    ];





    return (
        <Card>
            <IndexTable
                resourceName={resourceName}
                itemCount={indexContent.length}
                selectedItemsCount={
                    allResourcesSelected ? 'All' : selectedResources.length
                }
                onSelectionChange={handleSelectionChange}
                promotedBulkActions={promotedBulkActions}
                headings={[
                    { title: 'Name' },
                    { title: 'Type' },
                    { title: 'Start Date' },
                    { title: 'End Date' },
                    { title: 'Schedule' },
                    { title: 'Status' }
                ]}
            >
                {rowMarkup}
            </IndexTable>

        </Card>
    )

}

I'd like to know if it's possible to make the {rowMarkup} content dynamic.

Thanks.

What I did:

  1. Selected a row
  2. Performed action ("Activate")

What I expected:

The selected row to update

What happened

The API call was successful but the row didn't update.

0 Answers0