React实现类雅虎邮件系统页面离开自动保存草稿功能求助
实现React邮件草稿保存功能的方案
针对你遇到的useEffect进入页面就触发的问题,我们可以通过监听页面离开事件+表单内容变化判断的方式来实现需求,核心是只在用户输入内容且未提交、即将离开页面时才保存草稿。
具体实现步骤
1. 管理表单状态与初始值
首先用useState维护表单数据,同时保存初始值用来对比内容是否修改,再用useRef标记表单是否已提交,避免提交后重复保存草稿:
import { useState, useRef, useEffect } from 'react'; const EmailCompose = () => { // 表单初始值,可根据场景设置为空或编辑时的初始邮件内容 const initialForm = { to: '', subject: '', content: '' }; const [formData, setFormData] = useState(initialForm); const isSubmitted = useRef(false); // 表单输入更新逻辑 const handleInputChange = (e) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; // 表单提交处理 const handleSubmit = (e) => { e.preventDefault(); // 执行邮件提交逻辑 // ... isSubmitted.current = true; // 提交后重置表单 setFormData(initialForm); };
2. 监听浏览器关闭/刷新事件
使用useEffect绑定beforeunload事件,但只在表单内容有修改且未提交时,才保存草稿:
useEffect(() => { const handlePageUnload = (e) => { // 判断表单是否有内容变化 const hasContentChanged = Object.keys(formData).some(key => formData[key] !== initialForm[key]); if (hasContentChanged && !isSubmitted.current) { // 将当前表单内容存入草稿数组(替换成你的草稿数组更新逻辑) // 示例:setDrafts(prev => [...prev, { ...formData, draftTime: new Date() }]) // 可选:触发浏览器离开确认提示 e.preventDefault(); e.returnValue = ''; // 兼容多浏览器 } }; window.addEventListener('beforeunload', handlePageUnload); // 组件卸载时移除监听 return () => window.removeEventListener('beforeunload', handlePageUnload); }, [formData, initialForm]);
3. 处理单页路由跳转场景
如果是React Router的单页应用,还要监听路由跳转事件,避免用户通过路由切换离开页面时丢失草稿:
import { useLocation, useNavigate } from 'react-router-dom'; // 在组件内添加路由相关逻辑 const navigate = useNavigate(); const location = useLocation(); useEffect(() => { const handleRouteChange = () => { const hasContentChanged = Object.keys(formData).some(key => formData[key] !== initialForm[key]); if (hasContentChanged && !isSubmitted.current) { // 保存草稿到数组 // setDrafts(prev => [...prev, { ...formData, draftTime: new Date() }]) // 可选:提示用户确认离开 if (!window.confirm('您的邮件草稿未保存,确定要离开吗?')) { // 阻止路由跳转 navigate(-1); } } }; // 监听路由变化,组件卸载前执行判断 return () => handleRouteChange(); }, [formData, initialForm, navigate, location]);
核心优化点
- 避免无效触发:通过对比
formData和initialForm,只有内容真的变化时才执行保存逻辑,解决了useEffect初始触发的问题。 - 提交状态标记:用
useRef的isSubmitted确保提交后的内容不会被重复存入草稿。 - 全场景覆盖:同时处理浏览器关闭/刷新和单页路由跳转两种用户离开页面的情况。
内容的提问来源于stack exchange,提问作者FAAIZ ALAM
相关产品推荐
相关产品推荐

