Хук React - `useEffect` с очисткой - PullRequest
0 голосов
/ 03 августа 2020

Я изучаю React Hook и useEffect, но могу не понять ключевой момент его правильного использования.

У меня следующий сценарий:

  1. Если пользователь переключает раскрывающийся список, проверяет наличие флага isAnyChange из глобального состояния, есть ли какие-либо обновления на текущей странице.
  2. Если изменений нет, будет go вперед и перенаправит на следующую страницу,
  3. Если есть какие-либо изменения, отобразится диалоговое окно подтверждения.

Затем внутри диалогового окна подтверждения будут 2 кнопки:

  • 4.1 одна спрашивает для сохранения, проверки валидации и перенаправления
  • 4.2 запрашивается не сохранять и перенаправлять.

Я включаю вышеуказанный лог c с использованием другого useEffect, но я не уверен, правильно ли я поступаю, так как он выглядит подключенным ко мне и усложняющим вещи, тогда как лучше всего разложить мои функции? Я делаю правильный дизайн, используя эти local state flag для запуска разных useEffect? Я не мог придумать лучшего способа ...

const pageComponent = props => {
   const [isSelectChange, setIsSelectChange] = useState(false);
   const [canRedirect, setCanRedirect] = useState(false);
   const [isSaveCompleted, setIsSaveCompleted] = useState(false);

   const anyChange = useSelector(state => return state.anyChange;);
   const anyValidError = useSelector(state => return state.anyValidError;);

   // step 1. dropdown change to change local state and trigger useEffect in step 2
   const selectChange = () => {
      setIsSelectChange(true);
   }

   // step 2. state isSelectChange to trigger step 3 howConfirmDialog or useEffect in step 6
   useEffect(() => {
     if (isSelectChange) {
        if (anyChange) { showConfirmDialog(); }
        else { setCanRedirect(); }
        // should I placed it here? but this seems to trigger the same useEffect a second time even though no code is executing 
        // setIsSelectChange(false);
     }

     return () {
        // clean up to reset the flag back to avoid looping here on isSelectChange, is it the right place to do it here?
        setIsSelectChange(false);
     }
   }, [isSelectChange])

   // step 3. dispatch a confirm dialog
   const showConfirmDialog() => {
      dispatch(openConfirmDialog(
        dialog: <ConfirmDialog confirmhdlr={saveAndRedirect} cancelhdlr={cancelAndRedirect} />
      );
   }

   // step 4.1 save and redirect
   const saveAndRedirect = async () => {
      await(savePage());
      // this is to trigger another useEffect monitoring on isSaveCompleted flag
      setIsSaveCompleted(true);
      setCanRedirect(true);
   }
   
   // step 4.2 cancel and redirect
   const cancelAndRedirect = () => {
      setCanRedirect(true);
   }
   
   // step 5. state isSaveCompleted to trigger
   useEffect(() => {
     if (isSaveCompleted && !anyValidError) {
        // this is to trigger another useEffect monitoring on "canRedirect"
        setCanRedirect(true);
        // should I placed it here? but this seems to trigger the same useEffect a second time even though no code is executing 
        // setIsSaveCompleted(false);
     }

     return () {
        // clean up to reset the flag back to avoid looping here on isSaveCompleted flag, is it the right place to do it here?
        setIsSaveCompleted(false);
     }
   }, [isSaveCompleted])

   // step 6. state canRedirect to trigger redirect
   useEffect(() => {
     if (canRedirect) {
       if (isSaveCompleted && !anyValidError) {
          // this is to trigger another useEffect monitoring on "canRedirect"
          setCanRedirect(true);
       }
       // should I placed it here? but this seems to trigger the same useEffect a second time even though no code is executing 
       // setCanRedirect(false);
     }

     return () {
        // clean up to reset the flag back to avoid looping here on canRedirect flag, is it the right place to do it here?
        setCanRedirect(false);
     }
   }, [canRedirect])

   return (<select onChange={selectChange}>)
}

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

1 Ответ

0 голосов
/ 03 августа 2020

Это не ответ, но он должен помочь вам лучше понять хук. У вас есть три эффекта useEffect, и каждый из них срабатывает каждый раз при изменении ЛЮБОГО состояния. Итак, ваш шаг 1 активирует все нижеуказанные useEffects. Используйте список зависимостей следующим образом:

useEffect(()=>{
  ...
}, [isSelectChange]) // this hook fires only when isSelectChange state changes.

useEffect(()=>{
  ...
}, []) // this hook fires only once, when the component ie rendering for the very first time
...