Editor’s note: This React inline editable UI tutorial was last updated on 30 March 2021.
User interfaces in React applications are becoming more complex by the day. As client-side UI libraries become increasingly powerful, we can create even more exciting user experiences by experimenting with React inline editable UI components such as editable tables, lists, and text fields.
Below is an example of a basic React inline editable UI:

In this tutorial, we’ll show you how to create basic inline editable UI components in React using a simplified version of Asana create task. Our editable UI will have only a task name and description field.
Here’s what we’ll cover:
- Popular inline editable UI tools
- React inline editable UI component libraries
- How editable UI works
- Building a simple React component for editable UI
- Exercise: Accessibility for forms with Tab key navigation
- When to use React inline editable UI
Here’s a demo of the React editable UI we’ll build in this walkthrough.
Popular inline editable UI tools
Below are some of the most prominent products currently using inline editable UI with clear UX.
- Asana: One of the best custom UIs with inline editable tables and forms
- Trello: Trello cards can be edited by clicking on them
- Airtable and Notion are some other modern apps that use inline editable UI elements
- Google sheets: Inline editable smart table UI for the web

Before going deep into our custom implementation of inline editable components, let’s talk about some of the existing React components you can use to achieve various inline editable UI elements.
React inline editable UI component libraries
Below are some inline editable UI component libraries for React.
React editable text field components
React Inline Edit Kit, successor to ReactInlineEdit, is a collection of common HTML form elements that are editable inline.
react-inline-editing
is a similar inline, editable text/label component for React.
These two packages are very simple and allow you to edit a label as an input box. You can customize the style based on your needs.
You can use React Inline Edit Kit and react-inline-editing
with any table-like structure to create a React editable table.
react-contenteditable
react-contenteditable
is arguably the most famous package for inline editable UI. The main difference between this component and others is that it allows you to inline edit HTML — not just text content.
This library can be used for markup and markdown editing in the UI. You can also manage the height of the editable element to create the look and feel of an input or a textarea
element. Check out an example on CodeSandbox.
React editable table library
React Table is one of the most popular table libraries that allows you to edit inline. You can create a UI similar to Google Sheets by customizing React Table library components.
In March 2020, React Table creator Tanner Linsley released React Table v7, which he described as “the culmination of over a years [sic] worth of work to refactor the entire library to a hooks-only UI/Style/Markup agnostic table building utility.”
See our comprehensive guide to building and stying tables with react-table
v7 for a closer look at what’s new in the most recent stable react-table
release, or read on to learn how to render your own React table component with react-table
.
You can also check out the React Table kitchen sink to see how this editable UI works in the table layout.
How editable UI works
Let’s explore how an editable UI works:
- An editable UI will simply display a label
- On hover, it will show the borders to make the UI look inline editable
- On click, it will transform the simple label to a custom input element. Some of the notable input elements are input fields,
textarea
, select component, date picker, etc. - By clicking
Enter
orEscape
, we’ll go back to the initial state and show the label - If you click
Tab
, it will once again switch to an input element and make the component accessible using the keyboard
For this tutorial, we’re going to build a simple version without the Tab
functionality.
You can easily add the Tab
functionality, but I left that as an exercise for you. You can create a pull request to my repo here.
Building a simple React component for editable UI
First, we’ll create a simple React app using create-react-app
.
I’m using tailwindcss
for styling. Read “How to use Tailwind CSS in React to configure Create React App” for more details.
Now let’s create the Editable
React component:
// Editable.js import React, { useState } from "react"; // Component accept text, placeholder values and also pass what type of Input - input, textarea so that we can use it for styling accordingly const Editable = ({ text, type, placeholder, children, ...props }) => { // Manage the state whether to show the label or the input box. By default, label will be shown. // Exercise: It can be made dynamic by accepting initial state as props outside the component const [isEditing, setEditing] = useState(false); // Event handler while pressing any key while editing const handleKeyDown = (event, type) => { // Handle when key is pressed }; /* - It will display a label is `isEditing` is false - It will display the children (input or textarea) if `isEditing` is true - when input `onBlur`, we will set the default non edit mode Note: For simplicity purpose, I removed all the classnames, you can check the repo for CSS styles */ return ( <section {...props}> {isEditing ? ( <div onBlur={() => setEditing(false)} onKeyDown={e => handleKeyDown(e, type)} > {children} </div> ) : ( <div onClick={() => setEditing(true)} > <span> {text || placeholder || "Editable content"} </span> </div> )} </section> ); }; export default Editable;
The component is very straightforward:
- If the
isEditing
state is true, then it displays the children. That’s where we pass theinput
ortextarea
elements. The input state will be managed outside of this component - If the
isEditing
state is false, then we display the simple labeltext
orplaceholder
depending on whether the text value is empty or not
Let’s see what a simple input editable component looks like:
// App.js - Input editable UI import React, { useState } from "react"; import Editable from "./Editable"; function App() { // State for the input const [task, setTask] = useState(""); /* Enclose the input element as the children to the Editable component to make it as inline editable. */ return ( <Editable text={task} placeholder="Write a task name" type="input" > <input type="text" name="task" placeholder="Write a task name" value={task} onChange={e => setTask(e.target.value)} /> </Editable> ); } export default App;
Here we enclosed input
inside the Editable
component. You can enclose any custom form component to make it an editable UI.
This is a pretty simple example. If you want to create a more complex example for editable UI you can create Higher order components
or custom Hooks to manage all the states outside the editable component.
Let’s see how the editable component works for a textarea
:
<Editable text={description} placeholder="Description for the task" type="textarea" > <textarea name="description" placeholder="Description for the task" rows="5" value={description} onChange={e => setDescription(e.target.value)} /> </Editable>
It’s that simple. We just swapped the input element with a textarea
, and it works as long as we provide the proper CSS based on the type we pass the Editable
component.
However, we’ll run into a few problems:
- When we click on the label, it won’t auto-focus on the input element
- A simple form can be navigated using the
Tab
key. However, an inline editable UI can’t be navigated without manually implementing that functionality
Solving the focus issue
To solve the focus issue, we need to use a reference to the input element and focus it when the edit state is set:
// App.js import React, { useRef, useState } from "react"; import Editable from "./Editable"; function App() { /* 1. create a reference using use reference and add the ref={inputRef} to input element 2. pass this reference to the Editable component, use different name than ref, I used `childRef`. Its basically a normal prop carrying the input element reference. */ const inputRef = useRef(); const [task, setTask] = useState(""); return ( <Editable text={task} placeholder="Write a task name" childRef={inputRef} type="input" > <input ref={inputRef} type="text" name="task" placeholder="Write a task name" value={task} onChange={e => setTask(e.target.value)} /> </Editable> ); } export default App;
Next, we’ll pass the input element reference to the Editable
component, then focus when the isEditing
state is true
:
// Editable.js import React, { useState, useEffect } from "react"; import "./Editable.css"; const Editable = ({ childRef, ... }) => { const [isEditing, setEditing] = useState(false); /* using use effect, when isEditing state is changing, check whether it is set to true, if true, then focus on the reference element */ useEffect(() => { if (childRef && childRef.current && isEditing === true) { childRef.current.focus(); } }, [isEditing, childRef]); const handleKeyDown = (event, type) => { ... }; return ( ... }; export default Editable;
Glitches with keydown events
There are a few things to be aware of when dealing with keydown events.
For the input element, all the keys (Enter, Escape and Tab key) will set the isEditing
state to false
.
For textarea
, the enter key has to add a new line inside textarea
, so we need to handle this use case separately:
const handleKeyDown = (event, type) => { const { key } = event; const keys = ["Escape", "Tab"]; const enterKey = "Enter"; const allKeys = [...keys, enterKey]; // All keys array /* - For textarea, check only Escape and Tab key and set the state to false - For everything else, all three keys will set the state to false */ if ( (type === "textarea" && keys.indexOf(key) > -1) || (type !== "textarea" && allKeys.indexOf(key) > -1) ) { setEditing(false); } }:
Exercise: Accessibility for forms with Tab
key navigation
By default, input and textarea
are hidden. As a result, we can’t navigate the form fields just by hitting the Tab
key.
To achieve keyboard support, we need to monitor the Tab
key event on the component or on the whole page and set the state manually to each element. Then we can navigate to the next form element on the next keypress.
We didn’t implement this in our example code, but it’s worth a try to make sure you can handle keypress events on a page in React.
When to use React inline editable UI
You don’t need to use inline editable UI for most basic form needs.
However, for complex React applications where you have lots of content with edit options, it’s best to build both view and edit in a single place. If you don’t, you’ll have to maintain two different UIs.
Limitations of inline editable UI in React
The most significant challenges you may run into in inline editable UI involve showing errors. You should account for this when thinking about the UX.
You may also have difficulty achieving the level of accessibility necessary to support mouse events. Touch events will likely also be an issue.
Finally, supporting mobile devices can be hard when you have form elements hidden. This will be especially tricky if the UI has to support a mobile layout, because there is no hover to show users whether the field is editable inline on touch screens.
Conclusion
This has been a simple example and overview on how to create inline editable components in React.
Try to use existing components, but if none of the existing ones fit your needs you can create custom ones.
You can check out the demo here and the codebase here.
Full visibility into production React apps
Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your React apps — start monitoring for free.
to solve the focus issue you can just add autoFocus property to your input element
or you could use a library like this https://www.npmjs.com/package/react-easy-edit
Hey, nice tut – I was trying by adding the tab functionality but did succeeded yet, if you can give some tips how to implement it would be appreciated.
Cheers,
Andrea
Is there a comparison of react-easy-edit (Mark A) with the other tools listed, and also do these other solutions cost money?