Shopify / shopify-app-template-remix

375 stars 151 forks source link

The useEffect does not be triggered and window object is not defined #813

Closed PhuocNguyen-synt closed 3 weeks ago

PhuocNguyen-synt commented 3 months ago

Hi,

I was trying to use the useEffect hook to add an event listener in my app._index.tsx file, but I couldn't figure out why the side effect wasn't being triggered when the app started. I suspect it's due to Server Side Rendering (SSR), which would prevent hooks or the window object from being used.

Thank you for your assistance.

TheGreatSimo commented 3 months ago

@PhuocNguyen-synt make sure your action function returns a different value each time. useEffect will only trigger when useActionData changes value. If useActionData always returns the same value, useEffect won’t run again after the initial update.

TheGreatSimo commented 3 months ago

Assuming you have useActionData variables in your useEffect dependency array

PhuocNguyen-synt commented 3 months ago

Hi @TheGreatSimo,

Thank you for your responses.

I'm currently using the useLoaderData variables as dependencies in my useEffect array instead of the useActionData hook (I was wondering if this might be causing a similar issue).

Here’s the code I'm working with:

`import * as React from 'react';
import { useLoaderData } from "@remix-run/react";

export default function Index() {
  console.log("HIT 1");
  const {A, B, C} = useLoaderData();

  React.useEffect(() => {
    console.log('HIT 2');
  }, []);

  React.useEffect(() => {
    console.log("HIT 3");
    const scrollListener = () => {
      console.log("HIT 4");
    };

    if (typeof window !== "undefined") {
      window.addEventListener("scroll", scrollListener);
    }

    return () => {
      if (typeof window !== "undefined") {
        window.removeEventListener("scroll", scrollListener);
      }
    };
  }, [A, B, C]);

  ...
}`

I’m able to see "HIT 1" in the terminal logs, but I’m not seeing "HIT 2", "HIT 3", or "HIT 4" in either the browser or terminal logs, though I expected them to appear.

Could you please offer some advice on this? Is this the same issue you mentioned earlier?

TheGreatSimo commented 3 months ago

@PhuocNguyen-synt during the initial server-side render the window object is not available which means the event listener cannot be added To fix this you can use your useEffect hook to conditionally add the event listener only when the component is mounted on the client-side Here's an example

import { useLoaderData } from "@remix-run/react";

export default function Index() {
  console.log("HIT 1");
  const { A, B, C } = useLoaderData();

  React.useEffect(() => {
    console.log('HIT 2');

    if (typeof window !== "undefined") {
      console.log("HIT 3");
      const scrollListener = () => {
        console.log("HIT 4");
      };
      window.addEventListener("scroll", scrollListener);

      return () => {
        window.removeEventListener("scroll", scrollListener);
      };
    }
  }, [A, B, C]);

  // Put your code here
}

On this code the useEffect hook checks if the window object is available before adding the event listener This means that the effect is only executed on the client-side and not during the initial server-side render

PhuocNguyen-synt commented 3 months ago

Hi @TheGreatSimo,

Thank you for your thoughtful responses.

I’ve attempted to use a condition before to check whether the window object exists , but unfortunately, I noticed that the log "HIT 2" never appears in the browser as I expected. This suggests that the useEffect is not being triggered when the app is initialized in the first time.

import * as React from 'react';
import { useLoaderData } from "@remix-run/react";

export default function Index() {
  console.log("HIT 1");
  const {A, B, C} = useLoaderData();

  React.useEffect(() => {
    console.log('HIT 2');
  }, []);

  React.useEffect(() => {
    console.log("HIT 3");
    const scrollListener = () => {
      console.log("HIT 4");
    };

    if (typeof window !== "undefined") {
      window.addEventListener("scroll", scrollListener);
    }

    return () => {
      if (typeof window !== "undefined") {
        window.removeEventListener("scroll", scrollListener);
      }
    };
  }, [A, B, C]);

  ...
}