Handling User Input in React and Out of React
Nitish Kumar Singh
Feb 22, 2024Hello developers! In this blog post, we will explore how we can handle user input in React and out of React, meaning the ways React provides to handle input and how we can write our own logic to handle user input in a better way than React.
Here, we will only discuss text inputs and handling input without adding input elements within a form element. To explore more about input handling in React go to its docs.
Handling User Input in React
React handles user input similarly to native input elements but with more control over user inputs. In React, we can handle user input as controlled input or simple input. What does controlled mean? It means that when a user enters some input, we first check that input and determine whether we want to accept that input or not.
To display an uncontrolled (simple) input element, we can simply add an input
tag as shown in the code below and retrieve the user-entered input using the myInput
reference.
<input ref={myInput} type="text"/>
This input
element is considered as uncontrolled input by React until we add the value
prop to it. After adding the value
prop, React considers this input
element as controlled and doesn't display any input entered by the user automatically.
When a user tries to enter any input, React prevents it and provides that entered input in the onChange
event handler if provided. In onChange
, we get that input by event.target.value
and update the state
to display that change as shown in the code below:
export default function Home() {
const [value,setValue] = useState("");
const change = (event)=>{
const newValue = event.target.value;
if (validate(newValue)) {
setValue(newValue);
}
}
return (
<div>
<input type="text" onChange={change} value={value}/>
</div>
)
}
Here, we have the chance to verify that input before displaying it to the user. But this can be problematic in some situations and/or provide a bad user experience.
Because in controlled input handling, input is not handled like a native element; instead, React provides the entered input without actually displaying it to the DOM, and when we change the state, it sets it to the element. Therefore, when a user tries to enter text at the beginning or anywhere except the end by moving the cursor (blinking line), the cursor automatically moves to the end, and this can be a bad user experience.
This is something we can solve by creating a custom React component.
Handling User Input out of React
We can handle user input with full control over inputs by creating a custom React component and writing logic code as required to validate and handle input. The code below is an example of that component:
import React, { Component, createRef } from 'react'
export default class EditText extends Component {
ref = createRef();
focus = ()=>{
this.focued = true
}
componentDidMount(){
this.ref.current.value = this.props.value;
}
input = (event)=>{
if(this.props.onChange) this.props.onChange(this.props.which, event.target.value);
}
blur = ()=>{
this.focued = false;
if(this.ref.current.value !== this.props.value) this.ref.current.value = this.props.value;
}
beforeInput = (event)=>{
if (this.props.isRightInput && !this.props.isRightInput(this.props.which, event.data)) event.preventDefault();
}
render() {
if(!this.focued && this.ref.current && this.ref.current.value !== this.props.value) this.ref.current.value = this.props.value;
return <input onBeforeInput={this.beforeInput} onChange={this.input} type={this.props.type} className={this.props.className}
style={this.props.style} ref={this.ref} onFocus={this.focus} onBlur={this.blur}/>
}
}
This component handles input like the native way of the browser with our validation. In componentDidMount
, it sets the provided value at first, and the first line of code in the render
method is used for external rendering (when its parent re-renders).
This component can be used for any purpose of input handling with memorization of purpose using the which
prop. It gives flexibility to enter input under validation (using isRightInput
function) and set the last validated value on blur
.
This component I have built to handle input of padding or margin like CSS strings. For example, if a user enters "10px 10
", it automatically sets "10px
" on blur because it is the last valid string for padding or margin.
You can customize it according to your requirements or build a new one that handles input outside of React. I hope this can help you. Happy Coding!