Skip to content

Navigating to the app admin page inconsistent (not awaiting till page loads properly? ) #950

@ninode97

Description

@ninode97

Problem

I am experiencing some re-rendering issues and unsure what could be causing this.

When I visit settings page (It load shops configuration from server), not sure why it for a moment of time renders previously active page, and then immediately it renders the page it should... (Attaching video below).

Screen.Recording.2025-01-31.at.11.37.15.mov

The settings page:

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const data = await authenticate.admin(request);
  const config = await prisma.config.findFirst({
    where: {
      shop: data.session.shop,
    },
  });
  return {
    brandColor: config?.brandColor,
    iconColor: config?.iconColor,
    icon: config?.icon,
  };
};

export const action = async ({ request }: ActionFunctionArgs) => {
  const formData = await request.clone().formData();
  const { session } = await authenticate.admin(request);
  const brandColor = formData.get("brandColor") as string;
  const iconColor = formData.get("iconColor") as string;
  const icon = formData.get("icon") as string;

  try {
    const config = await prisma.config.findFirst({
      where: { shop: session.shop },
    });
    if (!config) {
      throw new Error(`Config not found....`);
    }
    await prisma.config.update({
      where: { id: config.id },
      data: {
        brandColor,
        iconColor,
        icon,
      },
    });
    const result = {
      success: true,
      message: "Settings saved!",
    };
    return result;
  } catch (error) {
    const result = {
      success: false,
      message: "Error saving settings.",
    };
    console.error(result.message, error);
    return result;
  }
};

export default function SettingsPage() {
  const fetcher = useFetcher<typeof action>();

  useEffect(() => {
    if (fetcher.state !== "idle" || !fetcher.data) return;

    shopify.toast.show(fetcher.data.message, {
      duration: 2500,
      isError: !fetcher.data.success,
    });
  }, [fetcher.data, fetcher.state]);

  const settingsData = useLoaderData<typeof loader>();

  const [brandColor, setBrandColor] = useState<string>(
    settingsData.brandColor || "#111",
  );
  const [iconColor, setIconColor] = useState<string>(
    settingsData.iconColor || "#111",
  );
  const [iconStyle, setIconStyle] = useState<AvailableIcons>(
    (settingsData.icon as AvailableIcons) || "star2",
  );
  const wasChanged = useMemo(() => {
    return (
      settingsData.brandColor !== brandColor ||
      iconColor !== settingsData.iconColor ||
      iconStyle !== settingsData.icon
    );
  }, [
    brandColor,
    iconColor,
    iconStyle,
    settingsData.brandColor,
    settingsData.icon,
    settingsData.iconColor,
  ]);

  const handleClick = async () => {
    if (fetcher.state === "submitting") return;
    fetcher.submit(
      { icon: iconStyle, iconColor, brandColor }, // Data to send
      { method: "post" }, // Default is the current route's action
    );
  };

  return (
    <Suspense fallback="Loading...">
      <Page>
        <TitleBar title="Settings" />
        <Layout>
          <Layout.Section>
            <Card>
              <Text variant="headingSm" as="h2">
                Theme Settings
              </Text>
              <div className="mb-5"></div>
              <FormLayout>
                <Box
                  borderColor="border"
                  borderWidth="0165"
                  padding="150"
                  borderRadius="300"
                >
                  <InlineGrid gap="400" columns={3}>
                    <PopoverColorPicker
                      hexColor={brandColor}
                      setHexColor={setBrandColor}
                      label="Branding Color"
                    />
                    <PopoverColorPicker
                      hexColor={iconColor}
                      setHexColor={setIconColor}
                      label="Icon Color"
                    />
                  </InlineGrid>

                  <InlineGrid gap="100" columns={3}>
                    <PopoverReviewIconPicker
                      label={"Icon Style"}
                      icon={iconStyle}
                      setIcon={setIconStyle}
                      fill={iconColor}
                    />
                  </InlineGrid>
                </Box>
              </FormLayout>
            </Card>
            <PageActions
              primaryAction={{
                content: "Save",
                loading: fetcher.state === "submitting",
                disabled: !wasChanged,
                onAction: handleClick,
              }}
            />
          </Layout.Section>
        </Layout>
      </Page>
    </Suspense>
  );
}

What could be causing such behaviour for Settings Page ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions