React 18初始化与ApolloProvider组件适配问题求助
React 18 + Apollo Client 初始化问题解决指南
问题概述
按官方指南初始化React 18 + Apollo Client项目时,先后遇到两个核心错误:
- 初始使用
document.getElementById('app')时,报错:Error: createRoot(...): Target container is not a DOM element. - 改为
document.getElementById('root')后,出现useQuery相关错误:TypeError: Cannot read properties of null (reading 'useContext')
原代码片段
index.js
import { createRoot } from 'react-dom/client'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; import App from './App'; // Initialize Apollo Client const client = new ApolloClient({ uri: 'http://localhost:5000/graphql', cache: new InMemoryCache() }); // I have also tried with document.getElementById('root') // which exists at the public/index.html yet it also fails const container = document.getElementById('app'); console.log("container: "+container); const root = createRoot(container); root.render( <ApolloProvider client={client}> <App /> </ApolloProvider>, );
App组件
import React from 'react'; import ECGGraph from './ECGGraph'; function App() { return ( <div className="App" id="App"> <h1>ECG Data of Alice Johnson</h1> <ECGGraph /> </div> ); } export default App;
解决方案
1. 修复容器DOM元素不存在问题
- 匹配根容器ID:React项目默认根容器的ID是
root(定义在public/index.html中),你代码里的id="App"是组件内部元素,并非React挂载的根容器,必须用document.getElementById('root')获取正确容器。 - 确保DOM加载完成后执行初始化:如果脚本放在
head标签中,DOM未渲染完成会导致获取不到元素。可以把脚本移到body标签末尾,或者用DOM加载事件包裹初始化逻辑:
document.addEventListener('DOMContentLoaded', () => { const container = document.getElementById('root'); const root = createRoot(container); root.render( <ApolloProvider client={client}> <App /> </ApolloProvider> ); });
2. 修复useContext空值错误
- 升级Apollo Client版本:旧版本
@apollo/client不兼容React 18,执行npm install @apollo/client@latest升级到3.7+版本(该版本已完全适配React 18并发特性)。 - 规范useQuery调用范围:检查
ECGGraph组件,确保useQuery仅在被ApolloProvider包裹的组件内部调用,禁止在组件外部、未被包裹的组件或非React环境中使用。 - 修正render语法:React 18的
createRoot().render()不需要第二个参数,移除原代码中render方法末尾的多余逗号。
修正后的index.js代码
import { createRoot } from 'react-dom/client'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; import App from './App'; const client = new ApolloClient({ uri: 'http://localhost:5000/graphql', cache: new InMemoryCache() }); // 确保DOM加载完成后再初始化React应用 document.addEventListener('DOMContentLoaded', () => { const container = document.getElementById('root'); const root = createRoot(container); root.render( <ApolloProvider client={client}> <App /> </ApolloProvider> ); });
内容的提问来源于stack exchange,提问作者Victor Polo De Gyves Montero
相关产品推荐
相关产品推荐

