我正在学习React Hook和useEffect
,但我可能无法正确使用它。
我有以下场景:
- 如果用户切换下拉菜单,如果当前页面上有任何更新,将检查全局状态中是否有
isAnyChange
的标志 - 如果没有更改,将继续并重定向到下一页
- 如果有任何更改,将显示一个确认对话框
然后在确认对话框中,将有两个按钮:
- 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
呢?
这不是一个答案,但它应该有助于您更好地理解hook。您有三个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