如何在Express服务端设置Apollo Client的ReactiveVar响应式变量?
问题根源
Apollo Client 的 ReactiveVar 是仅运行在前端环境的内存变量,服务端和前端的代码运行在完全隔离的 runtime 环境中,你在服务端代码里导入修改的 currentUserVar 和前端组件读取的 currentUserVar 是两个完全独立的实例,修改服务端侧的变量自然不会同步到前端。
解决方法
场景1:普通CSR(客户端渲染)项目
前端主动调用接口拉取当前用户信息,再手动更新 ReactiveVar:
- 服务端新增一个
currentUserGraphQL 查询接口,接口内部解析请求携带的JWT cookie,返回对应的用户信息,未登录则返回默认的未登录状态结构。 - 前端在应用根组件、全局路由守卫或者Apollo Client初始化完成后触发这个查询,拿到结果后直接赋值给
currentUserVar:
// 定义查询 const GET_CURRENT_USER = gql` query GetCurrentUser { currentUser { id email user_name isLoggedIn } } ` // 根组件内触发查询更新reactiveVar const App = () => { const { data } = useQuery(GET_CURRENT_USER) useEffect(() => { if (data?.currentUser) { currentUserVar(data.currentUser) } }, [data]) return <DashboardComponent /> }
场景2:SSR(服务端渲染)项目
在服务端渲染阶段把用户信息注入到HTML全局变量,前端初始化时直接读取赋值:
- 服务端解析JWT拿到用户信息后,在返回的HTML中插入全局变量挂载用户信息:
// 服务端返回HTML的逻辑示例 const renderHTML = (currentUser) => { return ` <!DOCTYPE html> <html> <body> <div id="root"></div> <script> window.__INITIAL_USER__ = ${JSON.stringify(currentUser || { id: 0, email: '', user_name: '', isLoggedIn: false })} </script> </body> </html> ` }
- 前端初始化
currentUserVar时直接读取全局变量作为初始值:
// cache.tsx const initialUser = window.__INITIAL_USER__ || { id: 0, email: '', user_name: '', isLoggedIn: false } export const currentUserVar: ReactiveVar<ICurrentUser> = makeVar<ICurrentUser>(initialUser)
内容的提问来源于stack exchange,提问作者Peter Boomsma
相关产品推荐
相关产品推荐

