NextJS 14使用notistack 3.0.1触发enqueueSnackbar时出现NotFoundError
解决NextJS 14.0.4 + notistack 3.0.1 触发enqueueSnackbar时的removeChild错误
问题原因
这个错误是因为notistack的DOM挂载位置和NextJS的根节点结构冲突导致的。你的RootLayout把<Providers>放在了<html>标签外面,导致SnackbarProvider尝试操作不属于它管辖的DOM节点,卸载消息提示时就会出现「要移除的节点不是当前节点的子节点」的报错。
修复方案
1. 调整RootLayout的结构
把<Providers>移到<body>内部,让SnackbarProvider的上下文完全处于NextJS的根DOM节点(#__next)范围内:
const RootLayout = ({ children }: { children: React.ReactNode }) => { return ( <html lang="no"> <body id="__next"> <Providers> {children} </Providers> </body> </html> ) } export default RootLayout
2. 可选:手动指定挂载容器
如果调整结构后问题仍存在,可以手动指定notistack挂载到#__next节点,避免DOM操作冲突:
"use client" import { SnackbarProvider } from "notistack" import { useEffect, useState } from "react" export const Providers = ({ children }: { children: React.ReactNode }) => { const [container, setContainer] = useState<HTMLElement | null>(null) useEffect(() => { setContainer(document.getElementById("__next")) }, []) return ( <SnackbarProvider container={container}> {children} </SnackbarProvider> ) }
3. 规范enqueueSnackbar的调用
确保通过useSnackbar钩子获取enqueueSnackbar,且仅在客户端组件中调用:
"use client" import { useSnackbar } from "notistack" const MyComponent = () => { const { enqueueSnackbar } = useSnackbar() const handleSubmit = () => { enqueueSnackbar("操作成功", { variant: "success" }) } return <button onClick={handleSubmit}>触发提示</button> }
补充说明
NextJS的根布局中,<html>和<body>是框架控制的节点,把SnackbarProvider放在它们外面,会让消息提示元素挂载到错误的DOM层级。当提示要被移除时,React尝试从当前上下文的节点中删除它,但该节点实际属于更高层级的框架节点,最终抛出removeChild错误。
内容的提问来源于stack exchange,提问作者FransJoakim
相关产品推荐
相关产品推荐

