NextJS点击按钮加载组件异常:重复渲染且组件不显示
问题修复方案
核心问题
你的Woven组件被定义成了async函数,但React组件不能是异步函数(除非配合Suspense处理异步加载场景,但你的组件里没有任何异步操作)。React会把async组件返回的Promise当作无效的JSX节点,导致组件无法渲染,同时触发重复渲染逻辑,造成页面卡顿。
修复步骤
1. 修正Woven组件的定义
移除async关键字,组件内部没有await操作,完全不需要异步声明:
"use client" import { useState } from "react" // 移除async关键字 const Woven = () => { const [weaveApiKey, setWeaveApiKey] = useState('') const [weaveURL, setWeaveURL] = useState('') return( <> <form> <label> Weaviate API key: <input type="text" value={weaveApiKey} onChange={(e) => setWeaveApiKey(e.target.value)} /> </label> <br/> <label> Weaviate Cluster URL: <input type="text" value={weaveURL} onChange={(e) => setWeaveURL(e.target.value)} /> </label> <br/> </form> </> ) } export default Woven
2. 简化ToolsPage的渲染逻辑(可选)
可以直接在JSX中做条件判断,减少不必要的函数调用,让代码更直观:
"use client" import Woven from './components/weaved'; import Sidebar from './sidebar'; import { useState } from 'react'; const ToolsPage = () => { const [selectedTool, setSelectedTool] = useState(''); const handleToolClick = (tool: string) => { setSelectedTool(tool); }; return ( <> <Sidebar onToolClick={handleToolClick} /> <div> {selectedTool && ( <> <div>{selectedTool}</div> {selectedTool === 'weaviate' && <Woven />} </> )} </div> </> ); }; export default ToolsPage;
3. 优化Sidebar的key值(可选)
用tool字符串作为key而非index,避免后续添加更多工具时可能出现的列表渲染异常:
"use client" type SidebarProps = { onToolClick: (tool: string) => void; }; const Sidebar: React.FC<SidebarProps> = ({ onToolClick }) => { const toolNames = ['weaviate']; // 后续可添加其他工具名称 return ( <div> <h2>Tools</h2> {toolNames.map((tool) => ( <button key={tool} onClick={() => onToolClick(tool)}> {tool} </button> ))} </div> ); }; export default Sidebar;
补充说明
之前初始化为'weaviate'能显示,是因为第一次渲染时async组件的异常还没触发重复渲染循环;但点击按钮触发setSelectedTool更新状态后,React重新渲染时会检测到async组件的无效返回值,进而引发重复渲染卡顿。
内容的提问来源于stack exchange,提问作者Animo
相关产品推荐
相关产品推荐

