React Hook - несколько срабатываний useEffect на componentDidMount - PullRequest
1 голос
/ 01 августа 2020

Я использую несколько хуков useEffect для выполнения функций componentDidMount и componentDidUpdate, однако, похоже, когда компонент загружается, весь мой useEffect срабатывает изначально ...

const testComp = () => {
   const stateUserId = useSelector(state => { return state.userId; });
   const [userId, setUserId] = useState(stateUserId);
   const [active, setActive] = useState(false);
   const [accountId, setAccountId] = useState();
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      console.log('should trigger when userId changes...');
   }, [userId]);

   useEffect(() => {
      console.log('should trigger when active changes...');
   }, [active]);
   
   useEffect(() => {
      console.log('should trigger when accountId changes...');
   }, [accounted]);
  
   return (<div>...</div);
}

когда мои компоненты монтируются, я вижу там весь журнал консоли

component did mount...
should trigger when userId changes...
should trigger when active changes...
should trigger when accountId changes...

Как я могу позволить срабатывать только своему первому useEffect, а остальные три срабатывают только при изменении зависимости?

Ответы [ 3 ]

2 голосов
/ 01 августа 2020

useEffect не является прямой заменой componentDidMount и componentDidUpdate. Эффект будет запускаться после каждого рендеринга, поэтому вы видите все эти журналы консоли. Согласно документации React, второй параметр useEffect означает

, вы можете активировать их (эффекты) только при изменении определенных значений.

После начальный рендеринг, если компонент рендерится снова, только эффекты наблюдают за соответствующими изменениями значений.

Один из способов добиться желаемого - создать дополнительные переменные для хранения начальных значений и выполнять сравнения в useEffect когда нужно.

const testComp = () => {
  const initUserId =  useSelector(state => { return state.userId; });
  const stateUserId = initUserId;
   const [userId, setUserId] = useState(stateUserId);
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      if (userId !== initUserId) {
        console.log('should trigger when userId changes...');
      }
      
   }, [userId]);
  
   return <div>...</div>
}
1 голос
/ 01 августа 2020

вы можете использовать custom useEffect:

const useCustomEffect = (func, deps) => {
    const didMount = useRef(false);

    useEffect(() => {
        if (didMount.current) func();
        else didMount.current = true;
    }, deps);
}

и использовать его в своем компоненте:


useCustomEffect(() => {
      console.log('trigger when userId changes...');
}, [userId]);

1 голос
/ 01 августа 2020

Любой useEffect хук всегда будет запускаться при монтировании и компонента при изменении некоторых переменных в его массиве зависимостей. Если вы хотите выполнить действие только тогда, когда переменная изменится, вы должны сначала проверить входящее значение и выполнить необходимые проверки. Также ваш первый useEffect должен иметь пустой массив зависимостей, чтобы запускать его только при монтировании компонента, потому что он также будет вызываться при изменении userId.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...