Enhance your input fields with wait logic

Input fields that wait for a user to finish typing before performing an action are common feature in web applications. They can be tricky to get working so I wanted to show how I incorporated a wait timer into my input fields.

In my case, I needed a field that waits for users to finish typing in a few places. I already had an input component made with some custom styling, so I decided to extend the wait logic as a customizable feature.

For my example, Im using React, Typescript and Material UI.

Below is the complete example, I’ll step through the component piece by piece for the rest of the article.

interface IProps extends OutlinedTextFieldProps {  
waitForInput: boolean
}

Here I’m defining an interface with a custom property that extends the type used by Material UI Outlined Text Field component. This way I can use the component the same way I normally would, it just has one extra property.

const { waitForInput, ...inputProps } = props

You’ll get a console warning if you add an unknown property to a Material UI component, so I separate my custom property from the outlined text field ones.

const [waitEvent, setWaitEvent] = useState<React.ChangeEvent<HTMLInputElement>>(null)

This is where I store the text field onChange event while we wait for the user to stop typing.

useEffect(() => {  let timer = 0  if (waitEvent && waitForInput) {    timer = setTimeout(() => inputProps.onChange(waitEvent), 1000)  }  return () => clearTimeout(timer)}, [waitEvent])

I leverage useEffect to handle my wait logic. It will rerun every time is updated. If and are truthy, each change will reset the timeout to wait for 1 second.

const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {  if (waitForInput) {    event.persist() <- only for React 16 and earlier    setWaitEvent(event)  } else {    inputProps.onChange(event)  }}

Replacement for the standard onChange function. Adds a check for if we should use the wait logic or continue as normal.

return <TextField {...inputProps} onChange={onChange} />

return the standard Material UI text field component while spreading out all our properties. The onChange assignment should come after the spread of inputProps.

<ExtendedInput

waitForInput
variant="outlined" label="Extended Input" onChange={(e) => alert(e.target.value)}/>

Now you can use the component exactly as you would if it was the original Material UI version. With the added property available.

Former golf instructor turned software engineer. 4 years ago I left my job teaching golf in Beijing to pursue my passion for writing code.