useEffect 无法正常运行
useEffect don't operates properly
我正在研究 react.js。我的要求是在关闭选项卡时执行 API 调用。一旦 tab/browser 关闭,就会触发一个事件,从该触发的事件中,将调用 API 将值存储在数据库中。我已经在 useEffect() 中编写了代码,但由于此错误值存储在 DB 中,因此每次单击按钮时 API 都会获取。我已经添加了我的代码。谁能指出我代码中的错误并提供适当的解决方案。
const [formRegistered, setFormRegistered] = useState(false)
const initialFormState = {
firstname: '',
lastname: '',
email: '',
company: '',
presentation: false,
keyTakeaways: false,
whitepaper: false,
downloadAll: false
}
useEffect(() => {
return () => {
if( formRegistered){
window.addEventListener("beforeunload", function(e) {
e.preventDefault();
let confirmationMessage = "";
(e || window.event).returnValue = confirmationMessage;
handleSubmit(e)
return confirmationMessage ;
});
}
}
});
function formReducer(state, action) {
switch (action.type) {
case 'INSERT':
return { ...state, [action.field]: action.payload }
default:
return state
}
}
const [formState, dispatch] = useReducer(formReducer, initialFormState)
const updateForm = (e) => {
if (e.target.name == 'presentation') {
dispatch({ type: 'INSERT', field: 'presentation', payload: true })
} else if (e.target.name == 'keyTakeaways') {
dispatch({ type: 'INSERT', field: 'keyTakeaways', payload: true })
} else if (e.target.name == 'whitepaper') {
dispatch({ type: 'INSERT', field: 'whitepaper', payload: true })
} else if (e.target.name == 'downloadAll') {
dispatch({ type: 'INSERT', field: 'downloadAll', payload: true })
} else {
dispatch({ type: 'INSERT', field: e.target.name, payload: e.target.value })
}
}
const handleSubmit = async (e) => {
e.preventDefault()
const result = await fetch('/api/sample-API', {
method: 'POST',
body: JSON.stringify({ response: formState, type: 'download', anonymousID:
anonymousID })
})
setFormRegistered(false)
}
return (
{ formRegistered && <Col className='resource-download-button-container' sm={12} lg={4}>
<a target='_blank' download href='/'>
<Button id='resource-download-button' name='whitepaper' onClick={updateForm}
variant='dark'>
Whitepaper
</Button>
</a>
</Col>
<Col className='resource-download-button-container' sm={12} lg={12}>
<a target='_blank' download href='/'>
<Button id='resource-download-button' name='downloadAll' onClick={updateForm}
variant='dark'>
Download All
</Button>
</a>
</Col>
}
)
目前您的 useEffect() 挂钩将在每次操作时被调用,因为它不监听特定值的变化。
你需要包含在你的 useEffect 钩子中的是这样的:
useEffect(() => {
// your api call
}, [formRegistered]};
通过在 useEffect 钩子中的函数定义之后添加 [formRegistered],钩子将仅在 formRegistered 的值发生变化时执行,而不是在每次点击时执行。
编辑:我刚刚自己测试过,你是对的,这在关闭标签时不起作用。我通过这样的实现达到了你想要的结果:
useEffect(() => {
const executeOnClose = () => {
// your api call
}
window.addEventListener('beforeunload', executeOnClose);
return () => {
window.removeEventListener('beforeunload', executeOnClose);
}
}, []);
useEffects clean 回调仅在 unmounting
组件时触发...而不是在关闭应用程序时触发...为此,我建议为 beforeUnload
事件创建 eventListener:
useEffect(()=>{
window.addEventListener("beforeunload", onUnload);
return ()=> window.removeEventListener("beforeunload", onUnload)}
,[]);
我正在研究 react.js。我的要求是在关闭选项卡时执行 API 调用。一旦 tab/browser 关闭,就会触发一个事件,从该触发的事件中,将调用 API 将值存储在数据库中。我已经在 useEffect() 中编写了代码,但由于此错误值存储在 DB 中,因此每次单击按钮时 API 都会获取。我已经添加了我的代码。谁能指出我代码中的错误并提供适当的解决方案。
const [formRegistered, setFormRegistered] = useState(false)
const initialFormState = {
firstname: '',
lastname: '',
email: '',
company: '',
presentation: false,
keyTakeaways: false,
whitepaper: false,
downloadAll: false
}
useEffect(() => {
return () => {
if( formRegistered){
window.addEventListener("beforeunload", function(e) {
e.preventDefault();
let confirmationMessage = "";
(e || window.event).returnValue = confirmationMessage;
handleSubmit(e)
return confirmationMessage ;
});
}
}
});
function formReducer(state, action) {
switch (action.type) {
case 'INSERT':
return { ...state, [action.field]: action.payload }
default:
return state
}
}
const [formState, dispatch] = useReducer(formReducer, initialFormState)
const updateForm = (e) => {
if (e.target.name == 'presentation') {
dispatch({ type: 'INSERT', field: 'presentation', payload: true })
} else if (e.target.name == 'keyTakeaways') {
dispatch({ type: 'INSERT', field: 'keyTakeaways', payload: true })
} else if (e.target.name == 'whitepaper') {
dispatch({ type: 'INSERT', field: 'whitepaper', payload: true })
} else if (e.target.name == 'downloadAll') {
dispatch({ type: 'INSERT', field: 'downloadAll', payload: true })
} else {
dispatch({ type: 'INSERT', field: e.target.name, payload: e.target.value })
}
}
const handleSubmit = async (e) => {
e.preventDefault()
const result = await fetch('/api/sample-API', {
method: 'POST',
body: JSON.stringify({ response: formState, type: 'download', anonymousID:
anonymousID })
})
setFormRegistered(false)
}
return (
{ formRegistered && <Col className='resource-download-button-container' sm={12} lg={4}>
<a target='_blank' download href='/'>
<Button id='resource-download-button' name='whitepaper' onClick={updateForm}
variant='dark'>
Whitepaper
</Button>
</a>
</Col>
<Col className='resource-download-button-container' sm={12} lg={12}>
<a target='_blank' download href='/'>
<Button id='resource-download-button' name='downloadAll' onClick={updateForm}
variant='dark'>
Download All
</Button>
</a>
</Col>
}
)
目前您的 useEffect() 挂钩将在每次操作时被调用,因为它不监听特定值的变化。
你需要包含在你的 useEffect 钩子中的是这样的:
useEffect(() => {
// your api call
}, [formRegistered]};
通过在 useEffect 钩子中的函数定义之后添加 [formRegistered],钩子将仅在 formRegistered 的值发生变化时执行,而不是在每次点击时执行。
编辑:我刚刚自己测试过,你是对的,这在关闭标签时不起作用。我通过这样的实现达到了你想要的结果:
useEffect(() => {
const executeOnClose = () => {
// your api call
}
window.addEventListener('beforeunload', executeOnClose);
return () => {
window.removeEventListener('beforeunload', executeOnClose);
}
}, []);
useEffects clean 回调仅在 unmounting
组件时触发...而不是在关闭应用程序时触发...为此,我建议为 beforeUnload
事件创建 eventListener:
useEffect(()=>{
window.addEventListener("beforeunload", onUnload);
return ()=> window.removeEventListener("beforeunload", onUnload)}
,[]);