初始化ZegoCloud数据时Redux检测到非序列化值的解决求助
修复Redux存储ZegoUIKitPrebuilt实例的序列化错误
问题原因
Redux要求全局状态必须是可序列化的数据类型(比如普通对象、数组、字符串、数字等),而ZegoUIKitPrebuilt.create()返回的是包含内部方法、原型链的类实例,属于不可序列化的值,直接存入Redux就会触发"A non-serializable value was detected in the state"错误。
修复方案
方案1:用React Context管理Zego实例(最推荐)
把Zego实例放到React Context中,替代Redux存储,既能跨组件共享,又符合React状态管理逻辑。
- 创建ZegoContext文件:
// ZegoContext.js import { createContext, useContext } from 'react'; const ZegoContext = createContext(null); export const ZegoProvider = ZegoContext.Provider; export const useZego = () => useContext(ZegoContext);
- 修改Home.js,用Provider包裹组件并传入实例:
// Home.js import { ZegoProvider } from './ZegoContext'; import { useState } from 'react'; function Home() { const [zp, setZp] = useState(null); useEffect(() => { if (currentUser) { init(); } }, [currentUser]); async function init() { const userID = currentUser?.Username; const userName = 'userName' + userID; const { token } = await generateToken('https://node-express-vercel-master-one.vercel.app', userID); const KitToken = ZegoUIKitPrebuilt.generateKitTokenForProduction(1980920521, token, null, userID, userName); const newZp = ZegoUIKitPrebuilt.create(KitToken); newZp.addPlugins({ ZIM }); setZp(newZp); } if (!zp) return <div>加载中...</div>; return ( <ZegoProvider value={zp}> {/* 首页内容 */} </ZegoProvider> ); }
- 在调用组件中用useZego获取实例:
// 调用组件 import { useZego } from './ZegoContext'; function CallComponent() { const zp = useZego(); const { coachId } = useParams(); const chatId = useSelector((state) => state.chat.chatId); function handleSend(callType) { if (!zp) return; const targetUser = { userID: user?.username, userName: user?.username, }; zp.sendCallInvitation({ callees: [targetUser], callType: callType, timeout: 60, }) .then((res) => console.warn(res)) .catch((err) => console.warn(err)); } {/* 组件其他内容 */} }
方案2:在需要使用的地方动态创建实例(适合无需跨多组件共享的场景)
如果仅在少数组件中使用Zego实例,可以把初始化逻辑封装成可复用函数,需要时直接创建使用,避免存入Redux。
// 封装初始化函数 async function getZegoInstance(userID) { const userName = 'userName' + userID; const { token } = await generateToken('https://node-express-vercel-master-one.vercel.app', userID); const KitToken = ZegoUIKitPrebuilt.generateKitTokenForProduction(1980920521, token, null, userID, userName); const zp = ZegoUIKitPrebuilt.create(KitToken); zp.addPlugins({ ZIM }); return zp; } // 在调用组件中使用 function CallComponent() { const [zp, setZp] = useState(null); const user = useSelector(state => state.user); useEffect(() => { if (user?.username) { getZegoInstance(user.username).then(setZp); } }, [user]); function handleSend(callType) { if (!zp) return; const targetUser = { userID: user?.username, userName: user?.username, }; zp.sendCallInvitation({ callees: [targetUser], callType: callType, timeout: 60, }) .then(res => console.warn(res)) .catch(err => console.warn(err)); } {/* 组件其他内容 */} }
方案3:临时禁用Redux的序列化检查(不推荐)
如果一定要用Redux存储实例,可以关闭Redux Toolkit的序列化检查,但会导致时间旅行调试、状态持久化等功能失效,仅作为临时应急方案。
修改store配置:
// store.js import { configureStore } from '@reduxjs/toolkit'; import chatSlice from './chatSlice'; export const store = configureStore({ reducer: { chat: chatSlice, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredPaths: ['chat.zego'], }, }), });
内容的提问来源于stack exchange,提问作者Quang Phú Nguyễn Hoàng
相关产品推荐
相关产品推荐

