Event Listener in react functional component

Viewed 3752

Essentially, I have this function component, but I'm struggling with adding the listener just to this component, since right now it's going to the entire window. I tried using useRef, but that wasn't working. Any ideas?

const  AddReply =({item })=> {
        const {replies, setReplies, artists, setArtists, messages, setMessages, songs, setSongs, posts, setPosts, likes, setLikes, user, setUser, accesstoken, setAccesToken, refreshtoken, setRefreshtoken} = React.useContext(InfoContext);

        const refKey = useRef();
        function eventhandler(e) {
                if (e.code === 'Enter') {
                 handleSubmitReply();
                 console.log("Works");
               }
            }

        function handleSubmitReply(){
                console.log(document.getElementById("textareareply").value);
                const likesref=dbLikes.push(0);
                const likeskey=likesref.getKey();
                console.log("Likes key is ", likeskey);
               
                const ref = dbReplies.child(item['replies']).push({
                  'content':document.getElementById("textareareply").value,
                  'posterid': user.id,
                  'likes': likeskey,
                  "createdAt": {'.sv': 'timestamp'}
                });
            
              }
        useEffect(() => {
          
      // if I were to use useRef, then I tried using ref.current,
      // but then I got that "TypeError: refKey.current.addEventListener 
      // is not a function". 
          window.addEventListener("keyup", eventhandler);
          return () => {
            window.removeEventListener("keyup", eventhandler);
          };
        }, []);
      
        return(
                    
        <div>
                <TextArea id="textareareply" ref={refKey} rows={1} placeholder='Reply to post' /> 
                <Form.Button fluid positive onClick = {()=>handleSubmitReply()} style={{marginTop:"10px"}}>Reply</Form.Button> 
       </div>
)}

export default AddReply;``` 

2 Answers

Your useRef doesn't work probably because <TextArea> is a functional component so can't use ref. Instead, attach ref to the container:

      <div ref={refKey}>
          <TextArea id="textareareply" rows={1} placeholder='Reply to post' /> 
          <Form.Button fluid positive onClick = {()=>handleSubmitReply()}
                  style={{marginTop:"10px"}}>Reply</Form.Button> 
       </div>   

Then you can now attach event to it:

    useEffect(() => {
        const div = refKey.current;
        div.addEventListener("keyup", eventhandler);
        return () => {
            div.removeEventListener("keyup", eventhandler);
        };
    }, []);

That should solve your problem, but if you still prefer the current way of listening on window without useRef, then just add logic to the event handler to act only on your component:

    function eventhandler(e) {
        if (e.target.getAttribute('id') === 'textareareply') {            
            if (e.code === 'Enter') {
                console.log("Works");
            }
        }
    }

When we use a functional component, we pass directly the function reference into DOM event attributes, such as:

function AddReply() {
    
    function handleButtonClick(event) {
        console.log(event)
    }

    return (
        <button onClick={handleButtonClick}> Click Here </button>
    );
}
Related