React18拆分ApolloProvider组件后ReactDOM渲染报错求助
React 18 抽离ApolloProvider后渲染报错修复方案
问题复现
初始直接在index.js中配置ApolloProvider时,可正常连接Apollo Server,可用代码如下:
import { React } from 'react'; import * as ReactDOM from 'react-dom/client'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; import App from './App'; import { createHttpLink } from 'apollo-link-http'; const httpLink = createHttpLink({ uri: 'http://localhost:5002' }) const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache() }) const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <ApolloProvider client={client}> <App /> </ApolloProvider>, );
为实现代码解耦,新建ApolloProvider.js文件尝试将Apollo相关配置抽离为独立组件,代码如下:
import React from "react"; import App from "./App"; import { createHttpLink } from 'apollo-link-http'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; const httpLink = createHttpLink({ uri: 'http://localhost:5002' }) const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache() }) export default ( <ApolloProvider client = { client } > <App/> </ApolloProvider> )
修改index.js引入抽离后的组件执行渲染,代码如下:
import ReactDOM from 'react-dom'; import ApolloProvider from './ApolloProvider'; ReactDOM.render(ApolloProvider, document.getElementById('root'));
运行后触发报错:
ReactDOM.render is no longer supported in React 18. Use createRoot instead.

错误原因
- React 18 已完全废弃旧版
ReactDOM.render渲染API,必须从react-dom/client导入createRoot方法完成根节点挂载 - 抽离组件时命名与官方
ApolloProvider组件重名,易引发冲突;且直接硬编码App组件到Provider文件中,并未真正实现解耦 - 导入ReactDOM的路径错误,旧版
react-dom包下不存在适配React 18的渲染方法
正确修复方案
步骤1:优化抽离的Provider组件
修改ApolloProvider.js,封装为标准React组件,通过children接收子元素,避免硬编码App组件,同时规避和官方组件的命名冲突问题:
import React from "react"; import { createHttpLink } from 'apollo-link-http'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; const httpLink = createHttpLink({ uri: 'http://localhost:5002' }) const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache() }) // 自定义组件名避免和官方ApolloProvider重名 export default function CustomApolloProvider({ children }) { return ( <ApolloProvider client={client}> {children} </ApolloProvider> ) }
步骤2:修正index.js渲染逻辑
使用React 18标准的createRootAPI完成挂载,以JSX标签形式使用抽离的组件:
import * as ReactDOM from 'react-dom/client'; import App from './App'; import CustomApolloProvider from './ApolloProvider'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <CustomApolloProvider> <App /> </CustomApolloProvider> );
如果不需要保留组件的扩展性,也可以直接在抽离文件中导出写好App的JSX元素,在index.js中直接传入render方法渲染,该写法仅作兼容参考,不推荐在生产环境使用:
// index.js import * as ReactDOM from 'react-dom/client'; import ApolloApp from './ApolloProvider'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(ApolloApp);
内容的提问来源于stack exchange,提问作者Kelum
相关产品推荐
相关产品推荐

