添加输入框后Next.js应用在浏览器中卡顿冻结问题排查
问题根源及解决方案
核心问题:客户端组件误用了async函数
你给组件添加了"use client"标识,但同时将组件定义为async function skills()——Next.js的客户端组件不能是异步函数。React无法正确处理异步组件返回的Promise,会触发异常的渲染循环,直接导致页面冻结、内存异常波动。
修复步骤
- 移除组件的async关键字:客户端组件必须是同步函数,异步逻辑需放到
useEffect或专用数据获取钩子中处理。 - 迁移Firestore数据逻辑:如果需要从Firestore获取数据,把
getDocs这类异步操作放到useEffect内部,避免在组件顶层执行异步代码。 - 完善表单状态绑定:给title输入框补上状态绑定(可选,让逻辑更完整)。
修复后的代码
"use client" import { firebaseApp } from '@/app/firebase'; import React, { useState, useEffect } from 'react' import { collection, getDocs, getFirestore } from "firebase/firestore"; export default function skills() { const [title, setTitle] = useState(""); const [tags, setTags] = useState(""); const [skillsList, setSkillsList] = useState([]); // 将Firestore数据获取逻辑放到useEffect中 useEffect(() => { const fetchSkills = async () => { const db = getFirestore(firebaseApp); const skillsCollection = collection(db, "skills"); const skillsSnapshot = await getDocs(skillsCollection); const skillsData = skillsSnapshot.docs.map(doc => doc.data()); setSkillsList(skillsData); }; fetchSkills(); }, []); // 空依赖数组确保仅在组件挂载时执行一次 return ( <div> <form> <input type="text" name='title' id="title" placeholder='title' value={title} onChange={e => setTitle(e.target.value)} /> <input type="text" name='tags' id="tags" placeholder='tags(, separated)' value={tags} onChange={e => setTags(e.target.value)} /> <button type="button">+</button> </form> {/* 可选:展示从Firestore获取的技能数据 */} <ul> {skillsList.map((skill, index) => ( <li key={index}>{skill.title}</li> ))} </ul> </div> ) }
额外说明
- 你观察到的onChange触发多次重渲染、内存波动,本质是async组件导致的渲染异常,修复组件定义后这些问题会消失。
- 给表单按钮添加
type="button",可避免默认的表单提交行为(如果不需要提交表单的话)。
内容的提问来源于stack exchange,提问作者Ahan
相关产品推荐
相关产品推荐

