skip to Main Content

i have and useEffect inside my component

  useEffect(() => {
    const interval = setInterval(() => {
      setQueueState((pre) => {
        return pre.map((line) => {
          if (line.length === 0) return [];
          line[0].items = line[0].items > 0 ? line[0].items - 1 : 0;
          if (line[0].items > 0) {
            return [
              line[0],
              ...line.slice(1).filter((person) => person.items > 0)
            ];
          } else {
            return [...line.slice(1).filter((person) => person.items > 0)];
          }
        });
      });
    }, 4000);

    return () => {
      clearInterval(interval);
    };
  }, []);

What it basically does is to loop through an array of checkout lines and reduce the number of items of the first person in each line by 1. Now the problem with Strict Mode is that it gets reduced 2 times. I know it’s because Strict Mode renders a component 2 times. I just want to know a way to avoid this and still use Strict Mode.

2

Answers


  1. Chosen as BEST ANSWER

    thanks to the coment from Giorgi Moniava i rewrote the hook so it does not mutate the state and now it works as i wanted this is how the hook looks now

     useEffect(() => {
        const interval = setInterval(() => {
          setQueueState((prevState) => {
            const newQueueState = prevState.map((line) => {
              if (line.length === 0) return [];
              const firstPerson = {
                ...line[0],
                items: Math.max(0, line[0].items - 1)
              };
              const filteredLine = line
                .slice(1)
                .filter((person) => person.items > 0);
    
              if (firstPerson.items > 0) {
                return [firstPerson, ...filteredLine];
              } else {
                return filteredLine;
              }
            });
    
            return newQueueState;
          });
        }, 4000);
    
        return () => {
          clearInterval(interval);
        };
      }, []);
    

  2. As you pointed out, there are 2 renders with Strict mode on development. On my project, I create a hook called useEffectOnce.

    import { useEffect, useRef } from 'react'
    
    export const useEffectOnce = (effect: React.EffectCallback) => {
      const mounted = useRef(false)
      useEffect(() => {
        if (mounted.current) {
          return
        }
        mounted.current = true
        return effect()
        // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [])
    }
    

    and I use it like this:

    useEffectOnce(() => {
      // ...
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search