Next.JS“比上一次渲染时渲染了更多的钩子”
Posted
技术标签:
【中文标题】Next.JS“比上一次渲染时渲染了更多的钩子”【英文标题】:Next.JS "Rendered more hooks than during the previous render" 【发布时间】:2020-11-26 14:43:02 【问题描述】:我目前正在实施 useSWR,以便从我的 express 和 mongo-db 后端获取数据。我能够从数据库中成功获取数据没问题。以下是我用来实现此目的的代码:
```//SWR method for hydration
const fetcher = (...args) => fetch(...args).then(res => res.json())
const data, error = useSWR('http://localhost:3000/appi/daily', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>```
然后使用以下命令访问:
data.currentInfo.username
其中用户名是集合中的字段之一。
当我尝试将此信息添加到状态钩子中时出现问题,然后返回的错误呈现的钩子比上一次渲染时更多。
删除线:
const[displayNumber] = useState(data.currentInfo.randomString)
并且任何使用状态变量 displayNumber 的行都会完全修复错误。
我已经在下面包含了相关代码:
const fetcher = (...args) => fetch(...args).then(res => res.json())
const data, error = useSWR('http://localhost:3000/appi/daily', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
const[displayNumber] = useState(data.currentInfo.randomString)
//handler function for changing state variable
function handleNumChange(event)
console.log(event.target.value);
setNumber(event.target.value);
return(
<div>
<div>
<Navbar className="navbar"/>
<h2>data.currentInfo.username</h2>
<h2>displayNumber</h2>
简而言之,我使用 swr 提取数据,将此信息添加到状态变量,然后使用 h2 显示它。
谁能告诉我这种方法可能有什么问题?
我在网上搜索了错误,说它可能是由 useEffect 挂钩引起的,但我的代码中没有。
【问题讨论】:
将所有钩子移动到组件顶部和条件渲染之前 - reactjs.org/docs/… 嗨,如果我将钩子移到顶部,const[displayNumber] = useState(data.currentInfo.randomString) 上面的代码将不起作用,因为 data.currentInfo 尚未初始化 是的,然后你得到一个错误,我看到了 - 你需要将displayNumber
的初始状态设置为默认值,即useState(data && data.currentInfo && data.currentInfo.randomString || null)
您好,先生,我刚刚尝试了您的建议,但仍然收到相同的错误“初始化前无法访问'数据'”
对,完全按照下面答案中的建议进行操作,但在我之前的评论中添加检查。
【参考方案1】:
错误描述了你比以前的渲染有更多的钩子。如果你阅读了 react 文档,所有的 useState
钩子都应该在每次渲染时被调用。你不能有条件useState
,而你的代码有一个额外的useState
,如下:
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
这意味着如果没有error
并且只有data
则将调用const[displayNumber] = useState(data.currentInfo.randomString)
行。
编辑: 将其移到顶部通常可以解决您的问题。
const fetcher = (...args) => fetch(...args).then(res => res.json())
const data, error = useSWR('http://localhost:3000/appi/daily', fetcher)
//const[displayNumber] = useState(data.currentInfo.randomString) //Needs null checks ofcourse
//With null checks
const[displayNumber] = useState((data && data.currentInfo && data.currentInfo.randomString) || undefined)
//OR
//const[displayNumber] = useState(data?.currentInfo?.randomString)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
【讨论】:
把它移到顶部,你的意思是把状态钩子移到代码的顶部吗?将其移到数据获取之上会导致构建错误,因为数据尚未初始化。 您好,抱歉刚刚看到您的更新,它说 currentInfo 未定义。我已经在另一个页面上使用相同的方法实现了,如果在 swr 的最后一行之后的行 const[displayNumber] = useState(data.currentInfo.randomString)s 那么它能够获取数据 是的,您需要检查是否所有属性都已定义,您可以使用this。例如:useState(data?.currentInfo?.randomString)
或类似useState((data && data.currentInfo && data.currentInfo.randomString ) || undefined)
添加到答案中以上是关于Next.JS“比上一次渲染时渲染了更多的钩子”的主要内容,如果未能解决你的问题,请参考以下文章
Typescript next.js + i18n 的正确 getServerSideProps 语法
在 TypeScript 和 Next.js 中使用绝对导入解析模块