Checkout extensibility extension ui app infinite re-rendering loop

Hi, I am making my first checkout app and I have a problem of re-rendering when I use useEffect or useSubcription and I would need your help

const _deliveryGroups = useSubscription(deliveryGroups);

  const updateAttributes = async () => {
    if (isTargetSelected.current && dalMin && dalMax) {
      const res = await applyAttributeChange({
        type: 'updateAttribute',
        key: 'dal_min',
        value: dalMin.toISOString().slice(0, 10),
      });
      await applyAttributeChange({
        type: 'updateAttribute',
        key: 'dal_max',
        value: dalMax.toISOString().slice(0, 10),
      });
      console.log(res);
    }
  }

  useEffect(() => {
    if (isTargetSelected.current) {
      updateAttributes();
    }
  }, [_deliveryGroups, dalMin, dalMax]);

This for example makes an infinite loop when I click to change the shipping method, and as you can see I don’t change anything in updateAttributes (I use the function elsewhere so yes I need the condition to be there an not in the useEffect)

I have a console.log at the root of the extension function and as you can see it re-renders a lot but the weird thing is that it logs “res” (from updateAttributes) only once every 48 re-render, sometimes 84 ??? (or there is something I don’t understand?)

and it locks my navigator for a moment as when I click on “X” to close the tab it closes after maybe 30sec

Could the dependancies within useEffect be changing their values, triggering a re-render?

I have 2 useEffects: there is this one you see above, the other is to fetch some data and set dalMin and dalMax with an empty dependency array, I don’t use react that much and it is my first checkout app, I am maybe miss something so here is my code

import {
  Text,
  useApi,
  useTranslate,
  reactExtension,
  useSubscription,
} from '@shopify/ui-extensions-react/checkout';
import { useEffect, useState } from 'react';
import i18nIsoCountries from 'i18n-iso-countries';
i18nIsoCountries.registerLocale(require("i18n-iso-countries/langs/en.json"));

export default reactExtension(
  'purchase.checkout.shipping-option-item.render-after',
  () => 

My goal with all this is to get dalMin and dalMax (OK) and to put them in "custom attributes" of the order (also OK) but I have to update those attributes if client changes shipping method (and here it is not OK), I was also thinking about adding all the values into attributes and removing the ones I don't need in another extension on the payment (or thank you) page but as much as I know now there is no way to completly remove an attribute, I can put an empty string but there will always be the key visible on the admin page of the order, so if there was a way to stop the infinite loop and put the data into attributes it would be great.

thanks

Hi, I found the solution, in react do not use useSubscription, use the shopify hooks, hard to find this info by the way (or am I blind? I don’t know), for this situation I did that

const { isTargetSelected, shippingOptionTarget } = useShippingOptionTarget();
const applyAttributeChange = useApplyAttributeChange();

const updateAttributes = async () => {
  if (isTargetSelected && dalMin && dalMax) {
    await applyAttributeChange({
      type: 'updateAttribute',
      key: 'dal_min',
      value: dalMin.toISOString().slice(0, 10),
    });
    await applyAttributeChange({
      type: 'updateAttribute',
      key: 'dal_max',
      value: dalMax.toISOString().slice(0, 10),
    });
  }
}

if (isTargetSelected && shippingOptionTarget) {
  updateAttributes();
}

and with that when the client changes the shipping method it updates the attributes

2 Likes