0
import Card from '../UI/Card'
import CartItem from './CartItem'
import './Cart.css'
import { useEffect, useRef } from 'react'

const Cart = (props) => {

    let filteredCourses;
    let creditCount;
    let initialValue = 0;

    const isMounted = useRef(false);

        useEffect(() => {
          if (isMounted.current) {
            console.log("never again")
          } else {
            console.log("do something first time only")
            isMounted.current = true;
          }
  },[]);

    if(props.testing.length >0){
    filteredCourses = props.testing.filter((course) => {
        return course['theme'] ==="Software Engineering"});
        console.log("filtered",filteredCourses)
    }

    if(props.selection.length>0){
        let sum = props.selection.reduce(
            (previousValue, currentValue) => previousValue + currentValue.credits,
            initialValue
        )
        creditCount = "Number of credits: " + sum
    }

    let cartContents = props.selection.map(course => 
        <CartItem onRemove = {props.onRemove} title = {course.title} credits = {course.credits}/>)
    return(
        <Card className="cart">
            <h2>Module Selection
            </h2>
            {cartContents}
            {creditCount}
        </Card>
    )
}

export default Cart

With the following snippet I am looking to only run on first mount. Even though the dependency array is empty I believe this will be re run when the component is unmounted and remounted which I am looking to prevent. On first run through the ref will be false but thereafter it will always be true and so this block should never run again. However the else part of this block continues to render?

    const isMounted = useRef(false);

        useEffect(() => {
          if (isMounted.current) {
            console.log("never again")
          } else {
            console.log("do something first time only")
            isMounted.current = true;
          }
  },[]);
beeban
  • 23
  • 5
  • When the component unmounts, the state of your ref goes with it, so thats why it doesnt work. Your question is indicative you are trying to solve this in the wrong way. Can you tell us more about the thing you only want to run once? Typically, it may be more appropriate to manage that thing in the parent. – adsy Jul 30 '22 at 18:00
  • @AdamThomas thanks for the advice, I did not know that about ref value. I am looking to ensure that a fetch to an API occurs once and once only and not on mount. Therefore perhaps the best method would be to lift this up to parent and pass as props? This [link](https://stackoverflow.com/questions/59492626/stop-useeffect-from-running-on-mount/59492738#59492738) led me to believe that the above approach was possible – beeban Jul 30 '22 at 18:31
  • Correct, you should consider doing this in the parent instead. The linked question is solving a different problem -- running something only once on mount, even though the effect dependencies changed. This is different to your problem. – adsy Jul 30 '22 at 18:37

1 Answers1

0

useEffect will run twice with empty dependency array only when NODE_ENV == 'development' due to strict mode, in production it will run only once

to handle this in development you can set your ref to true on unmount

    const isMounted = useRef(false);

    useEffect(() => {
      if (isMounted.current || process.env.NODE_ENV === 'production') {
        console.log("do something first time only")
      }

      return () => {
        console.log("never again")
        isMounted.current = true;
      }
    },[]);
Mike
  • 801
  • 4
  • 7
  • What you put it true but according to the comments on the original question, the author is looking for the side effect to be run once even considering unmounts and remounts. I.e. if the component is unmounted and remounted, it somehow remembers and does not run the side effect the second (or more) times. The issue is therefore architectural and the thing they are trying to do needs moving. Fundamentally, it can only be fixed by hoisting state. – adsy Jul 30 '22 at 20:59
  • I also have strict mode removed from index.js or whichever file it lives in so it should not be rendering twice. I believe hoisting the state is the answer in the instance as per @AdamThomas – beeban Jul 31 '22 at 12:33