Next.js 13.4中useRef及Context渲染警告问题求助
解决Next.js 13.4中Context相关的警告问题
问题现象
在Next.js 13.4项目中使用useRef访问JSX元素时,控制台出现两个警告:
警告1
Warning: Rendering <Context.Consumer.Provider> is not supported and will be removed in a future major release. Did you mean to render <Context.Provider> instead? at Navbar (webpack-internal:///(app-client)/./src/components/Navbar.tsx:46:65) at ModalProvider (webpack-internal:///(app-client)/./src/context/ModalProvider.tsx:33:11) at App (webpack-internal:///(app-client)/./src/app/App.tsx:12:11) at body at html at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at RedirectBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at NotFoundBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/not-found-boundary.js:59:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at HotReload (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:276:11) at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:90:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:106:11) at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:387:13) at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:154:11) at RSCComponent at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:171:11)
警告2
Warning: Rendering <Context.Consumer.Consumer> is not supported and will be removed in a future major release. Did you mean to render <Context.Consumer> instead? at Navbar (webpack-internal:///(app-client)/./src/components/Navbar.tsx:46:65) at ModalProvider (webpack-internal:///(app-client)/./src/context/ModalProvider.tsx:33:11) at App (webpack-internal:///(app-client)/./src/app/App.tsx:12:11) at body at html at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at RedirectBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at NotFoundBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/not-found-boundary.js:59:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at HotReload (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:276:11) at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:90:11) at commitHookPassiveMountEffects (webpack-internal:///(app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:22022:7) at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:106:11) at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:387:13) at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:154:11) at RSCComponent at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:171:11)
相关代码
Navbar组件
'use client' import Link from 'next/link' import Logo from '@/logo.svg' import { useEffect, useRef } from 'react' const links = { About: '/', Project: '/project/list', Artist: '/artist/list', } type Menu = 'About' | 'Project' | 'Artist' export function MenuItem({ content }: { content: Menu }) { const link = links[content] if (!link) { return <>></> } return ( <Link href={link} className="poppins mr-4 mt-4 block text-[#171616]/50 hover:text-[#171616] hover:opacity-100 lg:mt-0 lg:inline-block" > {content} </Link> ) } export default function Navbar() { const menus: Menu[] = ['About', 'Project', 'Artist'] const navRef = useRef(null) useEffect(() => { console.log(navRef) }, [navRef]) return ( <nav ref={navRef} className="flex flex-wrap items-center border-b border-[#171616]/30 bg-white px-40"> <Link href="/" className="hidden lg:block"> <Logo className="mb-[30px] mt-[30px]" width="151px" height="45px" color="#171616" /> </Link> <div className="block flex flex-grow items-center"> <div className="flex flex-grow justify-center gap-24"> {menus.map((content, idx) => ( <MenuItem key={idx} content={content} /> ))} </div> <div className="rounded-[40px] px-[36px] py-[16px] text-right text-[18px] leading-none text-[#171616]/50 hover:border-transparent hover:bg-[#7960BE]/75 hover:text-white"> <Link href="/auth/login">Login</Link> </div> </div> </nav> ) }
ModalProvider组件
'use client' import { useReducer, createContext, ReactNode, Dispatch, useContext } from 'react' export type ModalState = { type: 'default' isOpen: boolean } type Action = { type: 'OPEN' } | { type: 'CLOSE' } type ToggleDispatch = Dispatch<Action> export const ModalStateContext = createContext<ModalState | null>(null) export const ModalSetterContext = createContext<ToggleDispatch | null>(null) // reducer function reducer(state: ModalState, action: Action): ModalState { switch (action.type) { case 'OPEN': return { ...state, isOpen: true, } case 'CLOSE': return { ...state, isOpen: false, } default: throw new Error('unhandled action') } } export function ModalProvider({ children }: { children: ReactNode }) { const [state, dispatch] = useReducer(reducer, { type: 'default', isOpen: false }) return ( <ModalStateContext.Provider value={state}> <ModalSetterContext.Provider value={dispatch}>{children}</ModalSetterContext.Provider> </ModalStateContext.Provider> ) }
App组件
'use client' import { ModalProvider } from '@/context/ModalProvider' import ModalContainer from '@/components/modal/ModalContainer' export default function App({ children }: { children: React.ReactNode }) { return ( <ModalProvider> {children} <ModalContainer /> </ModalProvider> ) }
解决方案
警告的核心问题是错误地渲染了Context.Consumer.Provider或Context.Consumer.Consumer,从调用栈来看,问题出在你未提供代码的ModalContainer组件中,需要检查其中使用Context的方式:
正确的Context使用方式
有两种标准方式可以使用React Context:
- 使用
useContext钩子(推荐)
'use client' import { useContext } from 'react' import { ModalStateContext, ModalSetterContext } from '@/context/ModalProvider' export default function ModalContainer() { const modalState = useContext(ModalStateContext) const modalDispatch = useContext(ModalSetterContext) if (!modalState || !modalDispatch) { return null } return ( // 你的Modal内容,根据state和dispatch处理逻辑 modalState.isOpen && <div className="modal">...</div> ) }
- 使用
Consumer组件
'use client' import { ModalStateContext, ModalSetterContext } from '@/context/ModalProvider' export default function ModalContainer() { return ( <ModalStateContext.Consumer> {(state) => ( <ModalSetterContext.Consumer> {(dispatch) => { if (!state || !dispatch) return null return ( // 你的Modal内容 state.isOpen && <div className="modal">...</div> ) }} </ModalSetterContext.Consumer> )} </ModalStateContext.Consumer> ) }
需要避免的错误写法
- 不要重复访问
Consumer属性:ModalStateContext.Consumer.Consumer - 不要从
Consumer上访问Provider属性:ModalStateContext.Consumer.Provider
修正ModalContainer中的Context使用代码后,这两个警告就会消失。
内容的提问来源于stack exchange,提问作者KSoonYo
相关产品推荐
相关产品推荐

