首页 > 解决方案 > NextJS Button 通过 React 的 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>
        </>
    )
}

标签: reactjsbuttonnext.jsuse-statereact-functional-component

解决方案


如果不深入研究上下文和thisjavascript 中的绑定,问题就出在您的onClick处理程序中。有几种方法可以解决它,但要点是你需要有一个函数来在处理 DOM 元素上的事件时调用你的更新/提交函数。

这个想法是你绑定一个函数来处理事件,然后在事件发生时调用你的函数。

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

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(例如切换喜欢的状态),但您应该从以前的状态中读取以确保您没有得到错误的值。这样做的原因是状态更改是批处理的,而不是立即触发的。因此,您要确保在更新之前读取之前的值以防其他任何东西更新它):

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

推荐阅读