React钩子-具有清理功能的`useEffect`

时间:2020-08-03 16:01:35

标签: javascript reactjs react-hooks

我正在学习React Hook和useEffect,但是我可能无法正确使用它。

我有以下情况:

  1. 如果用户切换了下拉菜单,则将检查当前页面上是否有任何更新的全局状态的isAnyChange标志。
  2. 如果没有更改,将继续并重定向到下一页,
  3. 如有任何更改,将显示一个确认对话框。

然后在确认对话框中,将有2个按钮:

  • 4.1要求保存,检查验证并重定向,
  • 4.2人们要求不要保存和重定向。

我通过使用不同的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 :(得分:1)

这不是一个答案,但它应该可以帮助您更好地了解钩子。您有三个useEffects,每次更改ANY状态时,它们每个都起作用。因此,您的步骤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