onKeyDown get value from e.target.value?

Viewed 941

What's wrong with my way to handle input in react? I want to detect keycode and prevent them to be entered into the input, but now below code doesn't seem working.

const Input = ({ placeholder }) => {   const [inputValue, setInputValue] = useState("");

  const handleKeyDown = e => {
    console.log(e.target.value);
    if ([188].includes(e.keyCode)) {
      console.log("comma");
    } else {
      setInputValue(e.target.value);
    }   };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onKeyDown={handleKeyDown}
        placeholder={placeholder}
      />
    </div>   ); };

https://codesandbox.io/s/ancient-waterfall-43not?file=/src/App.js

5 Answers

you need to call e.preventDefault(), but also you need to add onChange handler to input:

  const handleKeyDown = e => {
    console.log(e.key);
    if ([188].includes(e.keyCode)) {
      console.log("comma");
      e.preventDefault();
    }
  };

const handleChange = e => setInputValue(e.target.value);
...

  <input
    type="text"
    value={inputValue}
    onChange={handleChange}
    onKeyDown={handleKeyDown}
    placeholder={placeholder}
  />

When you update the value of input, you should use onChange().

But, If you want to catch some character and treat about that, you should use onKeyDown().

So, in your case, you should use both.

this is an example code about backspace.

const Input = (props) =>{
  const [value, setValue] = React.useState('');

  function handleChange(e){
    setValue(e.target.value);
  }
  function handleBackSpace(e){
    if(e.keyCode === 8){
      //Do something.
    }
  }
  return (
    <div>
      <input onChange={handleChange} onKeyDown={handleBackSpace} value={value} type="text" />
    </div>
  )
}

```



Pass the value from Parent to child. Please check the below code.

import React, { useState } from "react";
import "./styles.css";

const Input = ({ placeholder, inputValue, handleKeyDown }) => {
  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onKeyDown={handleKeyDown}
        placeholder={placeholder}
      />
    </div>
  );
};

export default function App() {
  const [inputValue, setInputValue] = useState();

  const handleKeyDown = e => {
    console.log(e.keyCode);
    console.log(e.target.value);
    if ([40].includes(e.keyCode)) {
      console.log("comma");
    } else {
      setInputValue(e.target.value);
    }
  };
  return (
    <div className="App">
      <Input
        placeholder="xx"
        value={inputValue}
        handleKeyDown={handleKeyDown}
      />
    </div>
  );
}

I think you should not use the onKeyDown event on this case to filter your input. The reason is that someone could simply copy and paste the content into the input. So it would not filter the comma character.

You should use the onChange event and add a Regex to test if the input is valid.

const Input = ({ placeholder }) => {
  const [inputValue, setInputValue] = useState("");

  const handleChange = e => {
    const filteredInput = e.target.value.replace(/[^\w\s]/gi, "");
    setInputValue(filteredInput);
  };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
        placeholder={placeholder}
      />
    </div>
  );
};

But how it works...

So the regex is currently allowing any word, digit (alphanumeric) and whitespaces. You could for example extend the whitelist to allow @ by doing const filteredInput = e.target.value.replace(/[^\w\s@]/gi, ""); Any rule inside the [^] is allowed. You can do some regex testing here https://regexr.com/55rke

Also you can test my example at: https://codesandbox.io/s/nice-paper-40dou?file=/src/App.js

Related