如何等待Strapi CMS返回ID后再执行发送邮件操作?
解决Apollo Client保存数据后等待ID返回再发送邮件的问题
我有个函数负责把数据保存到Strapi CMS,保存后会生成一个ID,我想用这个ID调用发送邮件的函数。但现在的问题是,用户点击按钮后,数据先发送到CMS,但还没等ID返回就执行了发邮件操作,导致第一次点击时ID是undefined;第二次点击时ID已经存在,邮件就能正常发送。我的需求是等ID可用后再执行发邮件操作。
现有代码
1. Apollo Client保存数据并获取ID的代码
const [newID, setNewID] = useState<number>(); const [addProject, { loading }] = useMutation(PROJECT_MUTATION, { onCompleted(data) { setSubmitted(true); setNewID(data.createdProject.data.id); // 在这里获取到ID }, onError() { setError(true); }, }); useEffect(() => { if ( imageUploaded ) { addProject({ variables: { title: formData.uploaderMail }, }) .catch((error) => { setError(true); }) .then(() => { setSubmitted(true); }); } }, [ addProject, formData.uploaderMail]);
2. 尝试用ID发送邮件的代码
const sendDEmailHandleClick = useCallback(() => { if (newID && formData.uploaderMail) { sendEmail( formData.uploaderMail, newID // 第一次点击时这里的ID是undefined ); setEmailError(""); } else { setEmailError("Something went wrong"); } }, [ formData.uploaderMail, newID ]);
3. 发送邮件工具函数
const sendEmail = async (uploaderMail, id) => { const sendEmail = await fetch( `/api/req/${uploaderMail}/${id}`, { method: "POST", headers: { "Content-Type": "application/json", }, } ); };
4. 发送邮件按钮
<Button type="submit" onClick={sendDEmailHandleClick} > Send email </Button>
解决方案
方法一:在Mutation完成后直接触发邮件发送
onCompleted会在数据保存成功、ID返回时触发,直接在这里调用发邮件函数,无需依赖状态更新的延迟:
修改useMutation配置:
const [addProject, { loading }] = useMutation(PROJECT_MUTATION, { onCompleted(data) { setSubmitted(true); const newID = data.createdProject.data.id; setNewID(newID); // 直接调用发邮件逻辑 if (formData.uploaderMail) { sendEmail(formData.uploaderMail, newID); setEmailError(""); } else { setEmailError("邮箱地址无效"); } }, onError() { setError(true); setEmailError("数据保存失败,无法发送邮件"); }, });
调整按钮逻辑,让按钮先触发数据保存(未保存时):
const sendDEmailHandleClick = useCallback(() => { // 未保存数据时先触发保存 if (!newID && imageUploaded) { addProject({ variables: { title: formData.uploaderMail }, }).catch(() => { setError(true); setEmailError("数据保存失败"); }); } else if (newID && formData.uploaderMail) { // 已有ID直接发邮件 sendEmail(formData.uploaderMail, newID); setEmailError(""); } else { setEmailError("请先完成数据上传"); } }, [ addProject, formData.uploaderMail, newID, imageUploaded ]);
方法二:监听newID变化自动触发邮件
用useEffect监听newID的更新,当ID变为有效值时自动发送邮件:
useEffect(() => { if (newID && formData.uploaderMail) { sendEmail(formData.uploaderMail, newID); setEmailError(""); } else if (newID) { setEmailError("邮箱地址无效"); } }, [newID, formData.uploaderMail]);
此时按钮只需负责触发数据保存:
const sendDEmailHandleClick = useCallback(() => { if (imageUploaded) { addProject({ variables: { title: formData.uploaderMail }, }).catch(() => { setError(true); setEmailError("数据保存失败"); }); } else { setEmailError("请先完成图片上传"); } }, [ addProject, formData.uploaderMail, imageUploaded ]);
方法三:禁用按钮直到ID可用
在UI层面限制,当newID不存在或数据正在保存时禁用按钮,避免用户过早点击:
<Button type="submit" onClick={sendDEmailHandleClick} disabled={!newID || loading} > {loading ? "保存中..." : "Send email"} </Button>
内容的提问来源于stack exchange,提问作者FD3
相关产品推荐
相关产品推荐

