简体   繁体   English

React 钩子 - 带有清理功能的 useEffect

[英]React hook - `useEffect` with clean up

I'm learning React Hook and useEffect but I might not get the key point of using it correctly.我正在学习 React Hook 和useEffect ,但我可能没有掌握正确使用它的关键点。

I have a following scenario:我有以下情况:

  1. If a user switches the dropdown, will check if a flag of isAnyChange from the global state if there is any update on the current page.如果用户切换下拉列表,将检查是否有来自全局 state 的isAnyChange标志,如果当前页面上有任何更新。
  2. If there is no change, will go ahead and redirect to next page,如果没有变化,会提前go重定向到下一页,
  3. If there is any change, will display a confirm dialog.如果有任何变化,将显示一个确认对话框。

Then inside the confirm dialog, will have 2 buttons:然后在确认对话框中,将有 2 个按钮:

  • 4.1 one asks for saving, checking the validation and redirect, 4.1 一个要求保存,检查验证和重定向,
  • 4.2 one asks for do not save and redirect. 4.2 一个要求不保存和重定向。

I am including the above logic with using different useEffect , but I am not sure if I am doing the correct way since it looks wired to myself and making things complicated, what'd be the best way to decomposite my functionality then?我使用不同的useEffect包括上述逻辑,但我不确定我是否在做正确的方法,因为它看起来与我自己有关并使事情变得复杂,那么分解我的功能的最佳方法是什么? am I doing the correct design here by using those local state flag to trigger different useEffect ?我在这里通过使用那些local state flag来触发不同的useEffect来做正确的设计吗? I couldn't think of any better way though...虽然我想不出任何更好的方法......

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}>)
}

as you see I have different flags to trigger different useEffect , I could do all of them in one function, then why would use useEffect here?如您所见,我有不同的标志来触发不同useEffect ,我可以在一个 function 中完成所有这些操作,那么为什么要在这里使用useEffect呢?

It is not an answer but it should help you to understand hook a bit better.这不是答案,但它应该可以帮助您更好地理解钩子。 You ve got three useEffects and each of them works every time when ANY state is changed.您有三个 useEffects,并且每次更改 ANY state 时,它们中的每一个都会起作用。 So your step 1 fires all useEffects below.因此,您的第 1 步会触发下面的所有 useEffects。 Use dependencies list like this:像这样使用依赖项列表:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM