React, edit text on doubleclick

By

Learn how to make text editable on double-click in React by toggling a state to swap a p element for an input, handling onChange and Enter and Escape keys.

~~~

To edit text on doubleclick in React, use a boolean state variable to swap a p element for an input field. Let’s build it.

I had the need to listen for a doubleclick event on an element, and make that element editable. Think of renaming a file in a list, or editing a todo item in place.

The toggle pattern

One way to do so is to use a toggle state variable, and when the element is doubleclicked we show a different element:

const [toggle, setToggle] = useState(true)
const [name, setName] = useState('test')

...

toggle ? (
  <p
    onDoubleClick={() => {
      setToggle(false)
    }}
  >{name}</p>
) : (
  <input
    type='text'
    value={name}
  />
)

When toggle is true we render the plain text. When the user doubleclicks it, we set toggle to false and the input appears in its place.

Notice we keep two separate pieces of state. toggle controls which element shows, name holds the actual text.

Making the input work

As written above, the input is broken. We assign the name state to its value prop, but there’s no way to change it, so React ignores your typing and prints a warning in the console: you provided a value prop without an onChange handler.

This is the classic controlled component pitfall. The fix is adding the onChange() event listener, which updates name on every keystroke.

Then we use onKeyDown() to intercept the Enter or Escape key press event and go back to showing the p element:

<input
  type='text'
  value={name}
  onChange={(event) => {
    setName(event.target.value)
  }}
  onKeyDown={(event) => {
    if (event.key === 'Enter' || event.key === 'Escape') {
      setToggle(true)
      event.preventDefault()
      event.stopPropagation()
    }
  }}
/>

Now typing updates the state, and pressing Enter or Escape flips toggle back to true, so the p element returns showing the new text.

You can also add any side effect into that function, for example to save the value somewhere if you have to. A common one is calling your API on Enter to persist the change.

A couple of refinements

You’ll probably want the field focused as soon as it appears, so the user can type right away. Add the autoFocus prop to the input.

Also notice that in this version Escape keeps the edited text, because both keys just close the field. If you want Escape to discard changes, store the original value in another state variable when editing starts, and restore it when Escape is pressed.

Tagged: React · All topics
~~~

Related posts about react: