React中异步调用后e.currentTarget对象为何变为null?
问题原因及解决方案
为什么e.currentTarget会变成null?
React的合成事件(React.FormEvent)采用事件池机制,事件触发后会将事件对象缓存起来供后续复用。当你的异步操作(addBook().then(...))完成时,原事件对象已经被React回收并重置,所以e.currentTarget就变成了null。
解决办法
方法1:提前保存表单元素引用
在异步操作开始前,把e.currentTarget赋值给一个变量,后续直接用这个变量操作表单:
onAddFormSubmitted(e: React.FormEvent<HTMLFormElement>): Promise<void> { e.preventDefault(); const form = e.currentTarget; // 提前保存表单引用 const formdata = new FormData(form); if (formdata) { const book: Book = { title: formdata.get("booktitle") as string, author: formdata.get("authorname") as string, } addBook(book).then((doc) => { book.id = doc.id; this.props.onBookCreated(book); form.reset(); // 直接用保存的引用重置 }); } }
方法2:使用e.persist()阻止事件池回收
调用e.persist()可以让React不把当前事件对象放回事件池,这样异步回调里还能访问到原事件对象:
onAddFormSubmitted(e: React.FormEvent<HTMLFormElement>): Promise<void> { e.preventDefault(); e.persist(); // 阻止事件对象被回收 const formdata = new FormData(e.currentTarget); if (formdata) { const book: Book = { title: formdata.get("booktitle") as string, author: formdata.get("authorname") as string, } addBook(book).then((doc) => { book.id = doc.id; this.props.onBookCreated(book); e.currentTarget.reset(); // 现在能正常访问了 }); } }
注意:这种方式会跳过事件池优化,频繁使用可能影响性能,更推荐方法1。
方法3:使用React Ref直接获取表单元素
如果组件结构允许,用createRef(类组件)直接引用表单元素,操作起来更直观可靠:
// 类组件示例:先在constructor里创建ref constructor(props) { super(props); this.bookFormRef = React.createRef<HTMLFormElement>(); } // 表单元素绑定ref <form ref={this.bookFormRef} onSubmit={this.onAddFormSubmitted}> {/* 表单内容 */} </form> // 提交函数里直接用ref操作 onAddFormSubmitted(e: React.FormEvent<HTMLFormElement>): Promise<void> { e.preventDefault(); const form = this.bookFormRef.current; if (!form) return; const formdata = new FormData(form); if (formdata) { const book: Book = { title: formdata.get("booktitle") as string, author: formdata.get("authorname") as string, } addBook(book).then((doc) => { book.id = doc.id; this.props.onBookCreated(book); form.reset(); // 用ref重置表单 }); } }
内容的提问来源于stack exchange,提问作者Mahfuzur Rahman
相关产品推荐
相关产品推荐

