NextJS+Firebase评论系统按钮自动触发点击问题求助
解决Next.js + Firebase评论系统自动提交的问题
嘿,你的问题根源其实不是useState,而是提交按钮的onClick绑定方式错了!咱们一步步拆解解决:
问题核心
你现在的按钮代码是这样的:
<Button ... onClick={submitComment(props.post, state.comment, state.comment)} >submit</Button>
这里的submitComment(...)是直接调用了函数,而不是把函数引用传给onClick。这就导致:
- 组件第一次加载时,这个函数会立刻执行一次
- 每当输入框触发setState(比如输入字符),组件重新渲染,这个函数又会被执行一次
这就是Firestore收到h、he、hey这类逐步输入内容的原因——每输入一个字符就触发一次提交!
快速修复方案
把onClick改成箭头函数包裹,这样只有点击按钮时才会调用提交函数:
<Button width="150%" type="secondary" ghost onClick={() => submitComment(props.post, state.name, state.comment)} > submit </Button>
(顺带帮你修正了一个小错误:你之前传了两次state.comment,应该是state.name对应用户名,state.comment对应评论内容)
进一步优化建议
- 拆分合并的state对象
把一个大state拆成独立的useState,更符合React最佳实践,也能减少不必要的组件重渲染:
const [liked, setLiked] = useState(false); const [comment, setComment] = useState(""); const [name, setName] = useState(""); // 对应的处理函数也能简化: const commentHandler = (e) => setComment(e.target.value); const nameHandler = (e) => setName(e.target.value); const toggleLike = () => setLiked(prev => !prev); // 用函数式更新更安全
- 用useCallback包裹提交函数
如果组件会频繁重渲染,把submitComment用useCallback包裹,避免每次渲染都创建新函数:
import { useCallback } from 'react'; const submitComment = useCallback((doc, name, text) => { // 加个简单的空值校验,避免提交空内容 if (!name.trim() || !text.trim()) return; firebase.firestore().collection('blogs').doc(doc).update({ comments: firebase.firestore.FieldValue.arrayUnion( { name: name, date: new Date().toString(), text: text } ) }) }, []); // 依赖为空,因为firebase实例是全局稳定的
- 改用表单提交事件
把输入框和按钮放在<form>标签里,监听onSubmit事件,这样既支持点击按钮提交,也支持回车提交,还能阻止默认行为:
const handleSubmit = (e) => { e.preventDefault(); // 阻止表单默认跳转行为 submitComment(props.post, name, comment); // 提交后清空输入框 setComment(""); setName(""); } // JSX部分调整: <form onSubmit={handleSubmit} className={styles.container}> <table className={styles.input} role="presentation"> {/* 原输入框代码不变 */} <tr> <td> <Button type="submit" // 改成submit类型 width="150%" type="secondary" ghost > submit </Button> </td> </tr> </table> </form>
这样修改后,自动提交的问题就彻底解决啦!
内容的提问来源于stack exchange,提问作者Foge Inator
相关产品推荐
相关产品推荐

