How to submit a form using Enter key in react.js?
Asked Answered
R

18

200

Here is my form and the onClick method. I would like to execute this method when the Enter button of keyboard is pressed. How ?

N.B: No jquery is appreciated.

comment: function (e) {
  e.preventDefault();
  this.props.comment({
    comment: this.refs.text.getDOMNode().value,
    userPostId:this.refs.userPostId.getDOMNode().value,
  })
},


<form className="commentForm">
  <textarea rows="2" cols="110" placeholder="****Comment Here****" ref="text"  /><br />
  <input type="text" placeholder="userPostId" ref="userPostId" /> <br />
  <button type="button" className="btn btn-success" onClick={this.comment}>Comment</button>
</form>
Regression answered 19/10, 2015 at 10:4 Comment(0)
D
328

Change <button type="button" to <button type="submit". Remove the onClick. Instead do <form className="commentForm" onSubmit={onFormSubmit}>. This should catch clicking the button and pressing the return key.

const onFormSubmit = e => {
  e.preventDefault();
  // send state to server with e.g. `window.fetch`
}

...

<form onSubmit={onFormSubmit}>
  ...
  <button type="submit">Submit</button>
</form>

Full example without any silly form libraries:

function LoginForm() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [submitting, setSubmitting] = useState(false)
  const [formError, setFormError] = useState('')

  const onFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    try {
      e.preventDefault();
      setFormError('')
      setSubmitting(true)
      await fetch(/*POST email + password*/)
    } catch (err: any) {
      console.error(err)
      setFormError(err.toString())
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <form onSubmit={onFormSubmit}>
      <input type="email" autoComplete="email" value={email} onChange={e => setEmail(e.currentTarget.value)} required />
      <input type="password" autoComplete="current-password" value={password} onChange={e => setPassword(e.currentTarget.value)} required />
      {Boolean(formError) &&
        <div className="form-error">{formError}</div>
      }
      <button type="submit" disabled={submitting}>Login</button>
    </form>
  )
}

P.S. Remember that any buttons in your form which should not submit the form should explicitly have type="button".

Discrimination answered 19/10, 2015 at 11:12 Comment(16)
why onSubmit={this.onCommentSubmit}> ?@DiscriminationRegression
@JasonBourne you can give the callback any name you want, I just always give event callbacks names like onSomethingClick, onMouseMove, onFormKeyPress etc, rather than name the method based on what it is supposed to do inside it, as sometimes that changes or is in another method (more testable)Discrimination
I have followed your instructions, But , on mouse click it is not working. Though it is working for Enter key, it is working when I am Hovering my choice over the button with Tabs key. Can you suggest a Better way? @DiscriminationRegression
@JasonBourne this is the correct and best practice method and it works in both instances, see jsfiddle.net/ferahl/b125o4z0Discrimination
In onCommentSubmit, you should also call event.preventDefault() and event.stopPropagation() to prevent the form from reloading the page (since its a form with a blank action attribute most likely)Vacationist
jamesfzhang's suggestion should be added to the answer in my opinion.Moria
It seems like If there are more than one button in the form, all other buttons must have type="button", otherwise the browser (Chrome in my case) will still "click" the first button in the sourceStays
Yep, buttons inside forms which don't have a type will default to 'submit' ^Discrimination
this does nothing for me. form still does not submit on 'enter'Expellant
Avoid page reload with an action='#' attribute to the form element.Feuilleton
The page shouldn't reload if you do e.preventDefault(); in the submit event @TerjeNorderhaugDiscrimination
This don't work on textarea tag. however, this work on <input type="text" > with the same solution.Empirin
@Empirin because textarea uses return key for line-breaks, seems like a bad idea to submit a form when focused in one?Discrimination
Old answer but this is a much better solution that using a key listener. I would say only bother with a key listener if you also need to customize other keys' actions.Trucker
I appreciate the simplicity of @TerjeNorderhaug's suggestion: <form action="#" onSubmit={this.onFormSubmit}>. And it works for me, whereas stopPropagation and preventDefault didn't do the trick in an async callback.Altruist
@WillsManley that's up for debate. Having html tags automatically implement application logic for the dev may not be desirable in all casesTetradymite
L
79

It's been quite a few years since this question was last answered. React introduced "Hooks" back in 2017, and "keyCode" has been deprecated.

Now we can write this:

  useEffect(() => {
    const listener = event => {
      if (event.code === "Enter" || event.code === "NumpadEnter") {
        console.log("Enter key was pressed. Run your function.");
        event.preventDefault();
        // callMyFunction();
      }
    };
    document.addEventListener("keydown", listener);
    return () => {
      document.removeEventListener("keydown", listener);
    };
  }, []);

This registers a listener on the keydown event, when the component is loaded for the first time. It removes the event listener when the component is destroyed.

Leialeibman answered 2/12, 2019 at 21:59 Comment(5)
I'm trying to have it submit a formData useState() hook - but it's submitting the "default" values - I'm assuming it's essentially a closure that can only use the values from when the listener is defined (?) -- should I just trigger a click on the submit button? or is there a way to directly call the executeSearch() function, but have it use the updated formData state?Poinciana
This method can't be used in React classes. Also to be clear the keyCode that has been deprecated is the DOM keyCode: developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode not part of ReactSpeedy
Similarly for those trying to prevent the Enter key from triggering a form submit, use event.preventDefault() as the replacement for callMyFunction()Pardon
@Pardon That's a really good point! Most people probably don't want to do the default action, so I've edited my answer to include this line now.Leialeibman
this is great but i like this https://mcmap.net/q/129658/-react-keypress-event-taking-only-initial-state-values-and-not-updated-valuesRummage
A
27

this is how you do it if you want to listen for the "Enter" key. There is an onKeydown prop that you can use and you can read about it in react doc

and here is a codeSandbox

const App = () => {
    const something=(event)=> {
        if (event.keyCode === 13) {
            console.log('enter')
        }
    }
return (
    <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <input  type='text' onKeyDown={(e) => something(e) }/>
    </div>
);
}
Amylo answered 2/12, 2019 at 23:15 Comment(1)
This works well, but in 2020 "event.keyCode" is depreciated, use "event.key". Also, if you are listening for the "Enter" key, it is: "event.key === "Enter"Parlormaid
U
26

Use keydown event to do it:

   input: HTMLDivElement | null = null;

   onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
      // 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
      if (event.key === 'Enter') {
        event.preventDefault();
        event.stopPropagation();
        this.onSubmit();
      }
    }

    onSubmit = (): void => {
      if (input.textContent) {
         this.props.onSubmit(input.textContent);
         input.focus();
         input.textContent = '';
      }
    }

    render() {
      return (
         <form className="commentForm">
           <input
             className="comment-input"
             aria-multiline="true"
             role="textbox"
             contentEditable={true}
             onKeyDown={this.onKeyDown}
             ref={node => this.input = node} 
           />
           <button type="button" className="btn btn-success" onClick={this.onSubmit}>Comment</button>
         </form>
      );
    }
Unruffled answered 30/1, 2018 at 15:52 Comment(1)
This causes premature form submission with some non-roman languages. For example, you need to use 'Enter' to make selection from numerous character options when typing in Japanese. You don't want to submit text when the user is making character selectionHaimes
S
4
import React, { useEffect, useRef } from 'react';

function Example() {

    let inp = useRef();
    useEffect(() => {
        if (!inp && !inp.current) return;
        inp.current.focus();
        return () => inp = null;
    });

    const handleSubmit = () => {
        //...
    }

    return (
        <form
            onSubmit={e => {
                e.preventDefault();
                handleSubmit(e);
            }}
        >
            <input
                name="fakename"
                defaultValue="...."
                ref={inp}
                type="radio"
                style={{
                    position: "absolute",
                    opacity: 0
                }}
            />
            <button type="submit">
                submit
            </button>
        </form>
    )
}

Sometimes in popups it would not work to binding just a form and passing the onSubmit to the form because form may not have any input.

In this case if you bind the event to the document by doing document.addEventListener it will cause problem in another parts of the application.

For solving this issue we should wrap a form and should put a input with what is hidden by css, then you focus on that input by ref it will be work correctly.

Sassenach answered 15/9, 2020 at 10:43 Comment(0)
D
3

If you don't have the form inside <form>, you could use this in componentDidMount():

componentDidMount = () => {
      document.addEventListener("keydown", (e) => 
        e.code === "Enter" && console.log("my function"))
    }
    
componentDidMount() //<-- remove this, it's just for testing here
Dogtooth answered 16/4, 2021 at 1:8 Comment(0)
E
2
useEffect(() => {
const keyEnter = event => {
      if (event.key === 'Enter') {
        event.preventDefault()
      }
    }

    document.addEventListener('keydown', keyEnter)

    return () => {
      document.removeEventListener('keydown', keyEnter)
    }
    }, [])
Elias answered 23/6, 2022 at 15:26 Comment(0)
E
1

I've built up on @user1032613's answer and on this answer and created a "on press enter click element with querystring" hook. enjoy!

const { useEffect } = require("react");

const useEnterKeyListener = ({ querySelectorToExecuteClick }) => {
    useEffect(() => {
        //https://mcmap.net/q/127374/-how-to-submit-a-form-using-enter-key-in-react-js
        const listener = (event) => {
            if (event.code === "Enter" || event.code === "NumpadEnter") {
                handlePressEnter();
            }
        };

        document.addEventListener("keydown", listener);

        return () => {
            document.removeEventListener("keydown", listener);
        };
    }, []);

    const handlePressEnter = () => {
        //https://mcmap.net/q/129659/-simulate-click-event-on-react-element
        const mouseClickEvents = ["mousedown", "click", "mouseup"];
        function simulateMouseClick(element) {
            mouseClickEvents.forEach((mouseEventType) =>
                element.dispatchEvent(
                    new MouseEvent(mouseEventType, {
                        view: window,
                        bubbles: true,
                        cancelable: true,
                        buttons: 1,
                    })
                )
            );
        }

        var element = document.querySelector(querySelectorToExecuteClick);
        simulateMouseClick(element);
    };
};

export default useEnterKeyListener;

This is how you use it:

useEnterKeyListener({
    querySelectorToExecuteClick: "#submitButton",
});

https://codesandbox.io/s/useenterkeylistener-fxyvl?file=/src/App.js:399-407

Examinant answered 4/10, 2020 at 15:47 Comment(0)
I
1

I have found this to be easier. Listen for the keyDown event on the input you want to submit by pressing 'Enter" key and handle the submit action with conditional ternary operator as show below in a single line.
This is mostly used on subscribing a newsletter where there's no need of a button to submit. Hope it helps.

<input 
     type="email" 
     placeholder="Email" 
     onKeyDown={e => e.key === 'Enter' ? handleSubmit : ''} />
Insole answered 26/5, 2022 at 17:48 Comment(0)
M
1

You can use <button type='submit'></button> with nothing in the middle.

Model answered 24/10, 2022 at 1:29 Comment(0)
L
1

You can change only button type => button to submit

    <form
        onSubmit={e => {
            e.preventDefault();
            handleSubmit(e);
        }}
       >
        <input
            name="developers"
            defaultValue="submit"
            ref={dev}
            type="radio"
        />
        <button type="submit">
            submit
        </button>
    </form>
Lockyer answered 1/2, 2023 at 12:43 Comment(0)
F
0

here is very optimised code

useEffect(() => {
    document
        .getElementById("Your-element-id")
        .addEventListener("keydown", function (event) {
            if (event.code === "Enter" || event.code === "NumpadEnter") {
                event.preventDefault();
                document.getElementById("submit-element").click();
            }
        });
}, []);
Fibroid answered 12/7, 2021 at 20:9 Comment(2)
Is this works in Mac?Lugubrious
@HydyrAvezberdiyew Yes, I have tested this code on mac itselfFibroid
F
0

use mousetrap
https://www.npmjs.com/package/mousetrap
https://www.npmjs.com/package/@types/mousetrap
(yeah, I know, unfortunatelly when You use typescript u have to install types aside from basic module)

import {bind} from 'mousetrap';

const handleSubmit = async () => {
// submit func here
};

bind(['enter', 'return'], handleSubmit);

other example of using mousetrap, maybe for other purpose:

bind(['command+k', 'ctrl+k'], function(e) {
    highlight([11, 12, 13, 14]);
    return false;
});
Fuddle answered 31/12, 2021 at 10:20 Comment(0)
T
0

So, I was looking for some solution around the same scenario where on the login page, after a user hits(press) enter button from keyboard should trigger login process.

You can configure the textbox with one of code,

<input
  // rest your code
  onKeyPress={ onkeyup }
/>

Please keep in mind I am using react hooks to achieve it, apart from that this link will help you understand more enter key event handler

Threesquare answered 17/2, 2022 at 18:44 Comment(0)
E
0

You may approach this problem like this.

   onKeyPress={e => e.key === 'Enter' && handleFormSubmit}
Ecdysis answered 6/3, 2022 at 17:32 Comment(0)
B
0

Try this:

const enterKye=()=>{
if(e.key==="Enter"){
  alert("hello");
  }
}
<input type="text" onKeyPress={enterKye}>
Brightness answered 17/3, 2022 at 12:46 Comment(0)
T
-1

for example next React+TS code(add use hooks for state and etc):


type Props = {
...any properties
} & [any other type if need]

//I want notice that input data type of component maybe difference from type of props
const ExampleComponent: React.FC<Props> = (props: [Props or any other type]){
     const anySerice = new AnyService();

     const handleSubmit = async (eventForm) => {
        await anySerice.signUp();
     }

     const onKeyUp = (event: KeyboardEvent) => {
        //you can stay first condition only
        if (event.key === 'Enter' || event.charCode === 13) { 
            handleSubmit(event)
        }
    } 
    
    ...other code
    
    return (<Form noValidate validated={validated} className="modal-form-uthorize" onKeyPress={onKeyUp}>

    ...other components form

    </Form>)
}

export default ExampleComponent;
Though answered 26/3, 2021 at 20:17 Comment(0)
K
-3

I solved this problem by sent autoFocus property in button

   <button autoFocus={true}></button>
Katha answered 12/8, 2021 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.