1

I call useEffect inside useContext and I want to know when this useEffect is called.

[settingContext.tsx]

// create context object
export const ColorContext = createContext<ColorContextType>(null);

export const ProductsProvider = (props) => {
  const { query } = useRouter();

  const [data, setData] = useState<ColorContextType>(null);
  useEffect(() => {
    async function fetchAPI() {
      const res = await fetch(`${env.API_URL_FOR_CLIENT}/page_settings/top`);
      const posts = await res.json();
      setData(posts);
    }
    fetchAPI();
  }, []);
  return <ColorContext.Provider value={data}>{props.children}</ColorContext.Provider>;
};

export const useColorContext = () => {
  const colors = useContext(ColorContext);
  let themeColor: string = '';
  let titleColor: string = '';

  if (colors !== null) {
    const colorData = colors.response.result_list[3].value;
    themeColor = JSON.parse(colorData).theme_color;
    titleColor = JSON.parse(colorData).title_color;
  }
  return { themeColor, titleColor };
};

[_app.tsx]

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <LayoutInitial>
      <ProductsProvider>
        <Component {...pageProps} />
      </ProductsProvider>
    </LayoutInitial>
  );
}

I use useColorContext on multiple components. It seems like useEffect is only called on '/' page, which is fine but I'm curious that useEffect should be called every time pages are rendered but it seems that it doesn't. is this because I use useContext?

Yuzu
  • 59
  • 1
  • 8

1 Answers1

0

The useEffect call is done in the ProductsProvider component which appears to only be rendered once, on page load/refresh. This is because components generally only re-render when a state they subscribe to is changed. If the useEffect were called directly within the <Component> component, it would be called every time the component is mounted (not in re-renders). useEffect is only called multiple times after mounting if one of its dependencies changes, which in your case, there are none.

For example: this sandbox

Edit lucid-jepsen-zwdfyv

It's composed of the App component, containing a Router to a homepage, a ComponentA route, and a ComponentB route. When each component mounts, its useEffect is called, creating an alert box. You'll only see the App useEffect alert once per page refresh.

ComponentA will have its useEffect called when the component mounts (every time you hit the /a route from a different route), and when the state in the component changes, since it's in the useEffect dependency array.

ComponentB will only have its useEffect called when the component mounts, and not when its state changes, because the state isn't included in the useEffect dependency array.

EDIT: To clarify, your useColorContext hook is not actually part of the ProductsProvider component, so the useEffect call is not "inherited" by any components that call the hook. Also, keep in mind when experimenting that using Strict Mode will cause components to render twice, allowing react to gather information on the first render, and display it on the second render.