NextJS Button 通过 React 的 useState 不断点击自己

NextJS Button keeps clicking itself by React's useState

我正在使用 nextjs 和 firebase 制作一个评论系统,但是当页面加载/用户在文本框中输入内容时,按钮“点击”自身并将文本框的当前值发送到 firestore

firestore 然后被垃圾邮件

h
he
hey

我怀疑是因为 useState,但我不确定我能做什么

这是我的代码中涉及 ​​useState 的部分:

const submitComment = (doc, name, text) => {
    firebase.firestore().collection('blogs').doc(doc).update({ 
        comments: firebase.firestore.FieldValue.arrayUnion(
            {
                name: name,
                date: new Date().toString(),
                text: text
            }
        )
    })
} 

export default function Feedback(props) {
    const [state, setState] = useState({
        liked: false,
        comment: "",
        name: ""
    })
    const toggleLike = () => setState({ ...state, liked: !state.liked })
    const commentHandler = (e) => setState({ ...state, comment: e.target.value })
    const nameHandler = (e) => setState({ ...state, name: e.target.value })

    return (
        <>
        <div className={styles.container}>
            <table className={styles.input} role="presentation">
                <tbody>
                    <tr>
                        <td rowSpan="2">
                            <Textarea 
                                id="text" 
                                status="secondary" width="100%" 
                                placeholder="Comments!" 
                                onChange={commentHandler}
                            />
                        </td>
                        <td>
                            <Input 
                                id="name" 
                                className={styles.name} 
                                width="100%" height="100%" status="secondary" 
                                placeholder="Name" 
                                onChange={nameHandler}
                            />
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <Button width="150%" type="secondary" ghost 
                                onClick={submitComment(props.post, state.comment, state.comment)}
                            >submit</Button>
                        </td>
                    </tr>
                </tbody>
            </table>           
        </div>
        </>
    )
}

你能试试在你的按钮上使用匿名回调吗:

onClick={() => submitComment(props.post, state.comment, state.comment)}

如果不深入研究上下文并在 javascript 中绑定 this,问题出在您的 onClick 处理程序中。有几种方法可以解决它,但要点是在处理 DOM 元素上的事件时,您需要有一个调用 update/submit 函数的函数。

我们的想法是绑定一个函数来处理事件,事件发生时该函数将调用您的函数。

一种方法是创建一个内联匿名函数:

onClick={() => submitComment(props.post, state.comment, state.comment)}

我个人更喜欢将此逻辑保留在组件主体之外,因此我宁愿将其移至靠近其余业务逻辑的位置:

// ev is the click event
const submitComment = (ev) => {
  // You can read from state & props here
  firebase.firestore().collection('blogs').doc(props.post).update({ 
    comments: firebase.firestore.FieldValue.arrayUnion({
      name: state.name,
      date: new Date().toString(),
      text: state.comment
    })
  })
}

// Later...
<button onClick={ submitComment }>Submit</button>

与点击问题完全无关,但在您调用的代码中也存在:

const toggleLike = () => setState({ ...state, liked: !state.liked })

我只是想指出,您可以在您的 setState 中使用当前状态(用于切换点赞之类的事情),但您应该阅读之前的状态以确保您没有得到一个坏的价值。这样做的原因是状态更改是分批处理的,而不是立即触发。所以你想确保你正在阅读以前的值 before 它被更新(以防其他任何东西正在更新它):

const toggleLike = () => {
  setState(prevState => { ...prevState, liked: !prevState.liked })
}