Home > Software design >  useEffect infinite loop WITH empty dependency array
useEffect infinite loop WITH empty dependency array

Time:09-23

I am dispatching a thunk from my useEffect to populate a table when the page loads. The useEffect keeps running infintely, even though I am using an empty dependency array. Here is my code:

const Cart = (props) => {
  const [didFetch, setDidFetch] = useState(false);
  useEffect( () => {
    async function fetchCart(){
      await props.getCartItems();
      setDidFetch(true);
    }
    fetchCart()
    return setDidFetch(false)
  },[]);

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>Product</TableCell>
            <TableCell align="right">Quantity</TableCell>
            <TableCell align="right">Total Cost</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {props.cartItems.map((item) => (
            <TableRow
              key={item.product.name}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row">
                {item.product.name}
              </TableCell>
              <TableCell align="right">{item.quantity}</TableCell>
              <TableCell align="right">
                {(item.quantity * item.product.price).toFixed(2)}
              </TableCell>
              <TableCell>
                <Button onClick={() => props.removeCartItem(item.id)}>
                  Remove
                </Button>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

CodePudding user response:

The cleanup function of useEffect should be an anonymous function, and you shouldn't set state variables inside it, as @windmaomao pointed out, it is a memory leak:

Suggestion

If you want to store a didFetch flag, I would use a ref for this purpose:

import {useRef} from 'react'

const Cart = (props) => {
  const fetched = useRef()
  useEffect( () => {
    async function fetchCart(){
      const res = await props.getCartItems();
      if(res) fetched.current = true
    }
    fetchCart()
    return () => fetched.current = false
  },[]);

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>Product</TableCell>
            <TableCell align="right">Quantity</TableCell>
            <TableCell align="right">Total Cost</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {props.cartItems.map((item) => (
            <TableRow
              key={item.product.name}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row">
                {item.product.name}
              </TableCell>
              <TableCell align="right">{item.quantity}</TableCell>
              <TableCell align="right">
                {(item.quantity * item.product.price).toFixed(2)}
              </TableCell>
              <TableCell>
                <Button onClick={() => props.removeCartItem(item.id)}>
                  Remove
                </Button>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

CodePudding user response:

Using your existing code it would be either:

Anonymous function

  const [didFetch, setDidFetch] = useState(false);
  useEffect( () => {
    async function fetchCart(){
      await props.getCartItems();
      setDidFetch(true);
    }
    fetchCart()
    return () => { 
        setDidFetch(false); 
    };
  },[]);

Named Function

  const [didFetch, setDidFetch] = useState(false);
  useEffect( () => {
    async function fetchCart(){
      await props.getCartItems();
      setDidFetch(true);
    }
    fetchCart()
    return function cleanup() { 
        setDidFetch(false); 
    };
  },[]);

Here are the useEffect docs for reference: https://reactjs.org/docs/hooks-effect.html

  • Related