【问题标题】:How to properly set keydown event listener to send message?如何正确设置 keydown 事件侦听器以发送消息?
【发布时间】:2022-06-18 23:29:24
【问题描述】:

我正在编写一个小型 聊天应用程序,但遇到了一些困难。应用程序正常工作,但我想设置 keydown 事件监听器来跟踪用户何时按下 Enter 以便他也可以通过这种方式发送消息(而不仅仅是手动单击 发送消息按钮)。

我使用 Firebasefirestore 作为数据库来保存消息。下面是 Chat.jsx 组件的完整代码:

import { useAuthState } from 'react-firebase-hooks/auth'
import { FirebaseContext } from '..'
import { useCollectionData } from 'react-firebase-hooks/firestore'
import firebase from 'firebase/compat/app'
import Loader from './loader/Loader'
import { generateRandomKey } from '../helpers/generateRandomKey'

const Chat = () => {
    const { auth, firestore } = useContext(FirebaseContext)

    const [user] = useAuthState(auth)
    const [value, setValue] = useState('')
    const [messages, loading] = useCollectionData(
        firestore.collection('messages').orderBy('createdAt')
    )

    const handleSendMessage = async () => {
        firestore.collection('messages').add({
            uid: user.uid,
            displayName: user.displayName,
            photoURL: user.photoURL,
            text: value,
            createdAt: firebase.firestore.FieldValue.serverTimestamp()
        })
        setValue('')
    } // useCallback?

    useEffect(() => {
        document.body.addEventListener('keydown', e => {
            if (e.key === 'Enter') {
                handleSendMessage()
            }
        })
        return () =>
            document.body.removeEventListener('keydown', e => {
                if (e.key === 'Enter') {
                    handleSendMessage()
                }
            })
    }, []) // what to put in deps?

    if (loading) return <Loader />

    return (
        <div className="content">
            <div>
                {messages.map(message => {
                    return (
                        <div key={generateRandomKey()}>
                            <div>
                                <img
                                    src={message.photoURL}
                                    alt="User avatar"
                                />
                                <p>{message.displayName}</p>
                            </div>
                            <p>{message.text}</p>
                        </div>
                    )
                })}
            </div>
            <div>
                <input
                    placeholder="Enter your message..."
                    value={value}
                    onChange={e => setValue(e.target.value)}
                ></input>
                <button onClick={handleSendMessage}>Send message</button>
            </div>
        </div>
    )
}

export default Chat

谈到问题 - 当我尝试通过 useEffect 设置事件侦听器时,每当我按下 Enter 时,它会发送两个空消息,然后是一个像这样的几条消息:

message: 'hello' -&gt; '' - '' - 'h' - 'he' - 'hel' - 'hell' - 'hello'

useEffect(() => {
    document.body.addEventListener('keydown', e => {
        if (e.key === 'Enter') {
            handleSendMessage()
        }
    })
    return () =>
        document.body.removeEventListener('keydown', e => {
            if (e.key === 'Enter') {
                handleSendMessage()
            }
        })
}, [handleSendMessage]) 

如果我用useCallback 钩子包裹handleSendMessage 并将[user, value, firestore] 放入deps,也会发生同样的情况。

问题:如何解决此问题并正确设置keydown 事件侦听器以通过按Enter 发送消息?

【问题讨论】:

    标签: javascript reactjs firebase event-handling use-effect


    【解决方案1】:

    我无意中解决了这个问题。我试图在 useEffect 钩子中设置 keydown 事件侦听器时以错误的方式思考。

    我所要做的就是在&lt;input /&gt; 元素中设置自定义事件,如下所示:

    <input
        placeholder="Enter your message..."
        value={value}
        onChange={e => setValue(e.target.value)}
        onKeyDown={handleKeyDown} //this one
    /> 
    

    然后添加一个处理程序:

    function handleKeyDown(e) {
        if (e.key === 'Enter') {
            if (value) {
                handleSendMessage()
            }   
        }
    }
    

    现在一切正常,我终于可以通过按 Enter 键发送消息而没有任何副作用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-31
      • 2014-08-21
      • 2020-09-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 2021-09-26
      • 1970-01-01
      相关资源
      最近更新 更多