真实开发踩坑:闭包捕获题目

打印 上一主题 下一主题

主题 985|帖子 985|积分 2955

本文为开发开源项目的真实开发经历,感兴趣的可以来给我的项目点个star,谢谢啦~
详细博文先容:开源|Documind协同文档(接入deepseek-r1、支持实时聊天)
  前置代码

zustand界说

  1. import {create} from "zustand";
  2. import {type Editor} from "@tiptap/react"
  3. interface EditorState{
  4.   editor:Editor | null;
  5.   setEditor:(editor:Editor|null)=>void;
  6. }
  7. export const useEditorStore = create<EditorState>()((set)=>({
  8.   editor:null,
  9.   setEditor:(editor)=>set({editor}),
  10. }))
复制代码
editor生存设置

这里为editor的生命周期,及editor总会实时生存到zustand中
  1.     onCreate({ editor }) {
  2.       setEditor(editor);
  3.     },
  4.     onDestroy() {
  5.       setEditor(null);
  6.     },
  7.     onUpdate({ editor }) {
  8.       setEditor(editor);
  9.     },
  10.     onSelectionUpdate({ editor }) {
  11.       setEditor(editor);
  12.     },
  13.     onTransaction({ editor }) {
  14.       //事务更新时,将编辑器设置到全局状态中
  15.       setEditor(editor);
  16.     },
  17.     onFocus({ editor }) {
  18.       //聚焦时,将编辑器设置到全局状态中
  19.       setEditor(editor);
  20.     },
  21.     onBlur({ editor }) {
  22.       //失去焦点时,将编辑器设置到全局状态中
  23.       setEditor(editor);
  24.     },
  25.     onContentError({ editor }) {
  26.       setEditor(editor);
  27.     },
复制代码
正文-ImageButton 组件

这里我为tiptap文本编辑器界说了一个图片文件,这里的逻辑就是点击CldUploadButton组件后在当地选择图片,选择图片后上传到cloudinary服务器成功之后触发onSuccess绑定的uploadPhoto事件,此中result?.info?.secure_url就是上传图片的云地点,将此地点传入onChange即可在tiptap文本编辑器中添加图片。
而在使用的过程中碰到了一个题目,下面代码中的console.log(editor)打印结果不一样,第一个打印为正常editor对象,而第二个console.log(editor)打印却是null,这就是由闭包捕获造成的。
为什么zustand总会实时生存editor状态还会打印null?因为editor在初始渲染为null的时间就被onChange()捕获,这个时间onChange()闭包内的editor就被赋值为null我将这里的editor引用取名为editor-1;之后editor的生命周期会实时触发zustand生存最新的editor状态(可参考前置代码),这个时间const { editor } = useEditorStore();中的editor则为最新的editor状态,我给其取名editor-2。editor-1是旧引用而editor-2是新引用,由于onChange()是个闭包,以是由于闭包捕获机制,闭包捕获并生存的是旧引用editor-1,而获取不到新引用editor-2,以是闭包内的console.log会打印null。
  1. import { useEditorStore } from "@/store/use-editor-store";
  2. import { ImageIcon } from "lucide-react";
  3. import { CldUploadButton } from "next-cloudinary";
  4. export const ImageButton = () => {
  5.   const { editor } = useEditorStore();//来自zustand
  6.   console.log(editor) //打印为最新editor对象
  7.   const onChange = (src: string) => {
  8.     console.log(editor) //打印为null
  9.     editor?.chain().focus().setImage({ src }).run();
  10.   };
  11.   const uploadPhoto = (result: any) => {
  12.     onChange(result?.info?.secure_url);
  13.   };
  14.   return (
  15.     <div className="flex flex-col items-center justify-center">
  16.     //cloudinary云图片上传组件
  17.       <CldUploadButton
  18.         options={{ maxFiles: 1 }}
  19.         onSuccess={uploadPhoto}
  20.         uploadPreset="kdm7bzdm"
  21.       >
  22.         <ImageIcon className="size-4" />
  23.       </CldUploadButton>
  24.     </div>
  25.   );
  26. };
复制代码
办理方案

直接在闭包函数内获取到当前zustand中的最新editor对象,这样我们就有效办理了闭包捕获题目。
  1. import { useEditorStore } from "@/store/use-editor-store";
  2. import { ImageIcon } from "lucide-react";
  3. import { CldUploadButton } from "next-cloudinary";
  4. import { useCallback } from "react";
  5. export const ImageButton = () => {
  6.   const onChange = (src: string) => {
  7.     console.log(editor);//打印为最新editor对象
  8.     const currentEditor = useEditorStore.getState().editor;
  9.     currentEditor?.chain().focus().setImage({ src }).run();
  10.   }
  11.   const uploadPhoto = (result: any) => {
  12.     onChange(result?.info?.secure_url);
  13.   };
  14.   return (
  15.     <div className="flex flex-col items-center justify-center">
  16.       {/* 图片插入下拉菜单 */}
  17.       <CldUploadButton
  18.         options={{ maxFiles: 1 }}
  19.         onSuccess={uploadPhoto}
  20.         uploadPreset="kdm7bzdm"
  21.       >
  22.         <ImageIcon className="size-4" />
  23.       </CldUploadButton>
  24.     </div>
  25.   );
  26. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表