How to Double Click to Edit Text in ReactJS

This article will use a simple React project to show you how to click (or double click) to edit a page’s text.

Here is a demo of the full name bio app we will build:

Double click to edit text animation

Notice that I’ve intentionally made the final outcome as simple as possible to avoid confusing you with unnecessary elements.

Without any further ado, let’s get started with the first step.

Step 1: Get the Right Node and NPM Version

Ensure that you have Node 10.16 (or greater) and NPM 5.6 (or greater) installed on your system.

Note:

Step 2: Create a New React App

Setup your React project by running:

npx create-react-app click-text-to-edit-project

In the snippet above, we used NPM’s create-react-app package to create a new React app called “click-text-to-edit-project”.

Alternatively, you can use Yarn to configure your project like so:

yarn create react-app click-text-to-edit-project

Step 3: Go Inside the Project Directory

After the installation process, navigate into the project directory like so:

cd click-text-to-edit-project

Step 4: Clean Up the src Folder

Inside the project directory’s src folder, delete all files except index.js and App.js.

Step 5: Remove Unnecessary Code

Open your index.js file and replicate the code below:

// index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

Also, open your App.js file and replicate the code below:

// App.js

import React from "react";
import { Component } from "react";

class App extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

export default App;

Note that the function component alternative of the snippet above is like so:

// App.js

import React from "react";

function App() {
  return (
    <div></div>
  );
}

export default App;

Step 6: Create a components Directory

In the src directory, create a new folder called components and move App.js inside it.

Step 7: Create an ElementMaker.js File

In the src/components directory, create a new file called ElementMaker.js.

Step 8: Create the ElementMaker Component

Here is where the wonders happen!

Open your ElementMaker.js file and replicate the code below. We will go through its explanation afterward.

// ElementMaker.js

import React from "react";
import { Component } from "react";

class ElementMaker extends Component {
  render() {
    return (
      <span>
        {
          /** Use ternary operator to specify <span>’s content */
          this.props.showInputEle ? (
            <input 
              type="text"
              value={this.props.value} 
              onChange={this.props.handleChange}
              onBlur={this.props.handleBlur} 
              autoFocus 
            />
          ) : (
            <span 
              onDoubleClick={this.props.handleDoubleClick}
              style={{ 
                display: "inline-block", 
                height: "25px", 
                minWidth: "300px", 
              }}
            >
              {this.props.value}
            </span>
          )
        }
      </span>
    );
  }
}

export default ElementMaker;

In the snippet above, we did the following:

  1. We created an ElementMaker component that uses React’s render() lifecycle method to render a <span> element.
  2. We used the ternary operator to specify the <span>’s inner content.
    In other words, the ternary operator says that if this.props.showInputEle’s value is truthy, the computer should use the given <input> element as the <span>’s inner content.
    However, if this.props.showInputEle’s value is falsy, the computer should use a second <span> element as the first <span>’s inner content.

And here is the function component alternative of the ElementMaker:

// ElementMaker.js

import React from "react";

function ElementMaker(props) {
  return (
    <span>
      {
        /** Use ternary operator to specify <span>’s content */
        props.showInputEle ? (
          <input 
            type="text" 
            value={props.value} 
            onChange={props.handleChange} 
            onBlur={props.handleBlur} 
            autoFocus 
          />
        ) : (
          <span 
            onDoubleClick={props.handleDoubleClick}
            style={{ 
              display: "inline-block", 
              height: "25px", 
              minWidth: "300px", 
            }}
          >
            {props.value}
          </span>
        )
      }
    </span>
  );
}

export default ElementMaker;

Keep in mind that we’ve not defined showInputEle—we will do that soon.

For now, though, you may have observed that we specified five attributes on the <input> element: type, value, onChange, onBlur, and autoFocus.

Here is the purpose of each attribute:

  • The type=“text” attribute specifies that the input element is a single-line text field.
  • We used the value attribute to set the input element’s content to the props parameter’s value property.
  • onChange is an event listener that will trigger the handleChange function whenever <input>’s value changes. Note that we will later define handleChange in our App component.
  • onBlur is an event listener that will trigger the handleBlur function whenever <input> loses focus. In other words, onBlur will invoke handleBlur whenever users click out of the input field. Note that we will later define handleBlur in our App component.
  • autoFocus is a Boolean attribute that tells the browser to focus automatically on the <input> element when the page loads.

◇ ◇ ◇

Notice that we also specified an onDoubleClick event listener on the second <span> element.

The onDoubleClick listener will trigger the handleDoubleClick function whenever users double click the <span> element.

Suppose you wish to make the text editable with a single click. In that case, simply change the onDoubleClick event listener to onClick.

Keep in mind that we will later define handleDoubleClick in our App component.

Step 9: Invoke the ElementMaker Component

Remember that we aim to display a full name bio that users can double click to edit.

So go back to your App.js file and replicate the code below. We will go through its explanation afterward.

// App.js

import React from "react";
import { Component } from "react";
import ElementMaker from "./ElementMaker";

class App extends Component {
  constructor() {
    super();
    this.state = {
      fullName: { text: "Joe Abraham", showInputEle: false },
    };
  }

  render() {
    return (
      <div>
        <h1>Double Click the Full Name’s Value to Edit</h1>
        <div>
          <strong>Full Name: </strong>
          <ElementMaker
            value={this.state.fullName.text}
            handleChange={(e) => 
              this.setState({ 
                fullName: { 
                  text: e.target.value, 
                  showInputEle: this.state.fullName.showInputEle, 
                },
              })
            }
            handleDoubleClick={() => 
              this.setState({
                fullName: { ...this.state.fullName, showInputEle: true },
              })
            }
            handleBlur={() => 
              this.setState({
                fullName: { ...this.state.fullName, showInputEle: false },
              })
            }
            showInputEle={this.state.fullName.showInputEle}
          />
        </div>
      </div>
    );
  }
}

export default App;

In the snippet above, we did the following:

  1. We imported our ElementMaker component from the ElementMaker.js file.
  2. We created an App component and set its state to a fullName object that contains a text property and a showInputEle property.
    • The text property stores each content the user types into ElementMaker‘s input element. Note that we used “Joe Abraham” as text’s default value.
    • The showInputEle property stores the Boolean value true or false. Remember that we used the showInputEle property in ElementMaker to determine the <span>’s inner content.
  3. In App‘s render() method, we used the <ElementMaker /> code to invoke the ElementMaker component. Then we passed some attributes to ElementMaker’s props parameter.
    The attributes we passed in are value, handleChange, handleDoubleClick, handleBlur, and showInputEle.
    • The value attribute got assigned App state’s fullName text property.
    • We assigned handleChange a function that updates the state’s fullName property with the ElementMaker‘s input element’s value.
    • We initialized handleDoubleClick with a function that updates state’s showInputEle property with the Boolean value true.
    • handleBlur got assigned a function that updates state’s showInputEle property with the Boolean value false.
    • We initialized showInputEle with the state’s showInputEle property.

Here is the function component equivalence of the App component:

// App.js

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

function App() {
  const [fullName, setFullName] = useState("Joe Abraham");
  const [showInputEle, setShowInputEle] = useState(false);

  return (
    <div>
      <h1>Double Click the Full Name’s Value to Edit</h1>
      <div>
        <strong>Full Name: </strong>
        <ElementMaker
          value={fullName}
          handleChange={(e) => setFullName(e.target.value)}
          handleDoubleClick={() => setShowInputEle(true)}
          handleBlur={() => setShowInputEle(false)}
          showInputEle={showInputEle}
        />
      </div>
    </div>
  );
}

export default App;

Step 10: Making Sense of It All

So, now that we’ve done the coding aspect, let’s discuss how the browser will implement it all.

  1. The browser will read App.js and render its <h1> and <strong> elements.
  2. On getting to the <ElementMaker /> code, the browser will invoke the ElementMaker component and pass in the specified attributes to its props parameter.
  3. ElementMaker will return its <span> element. But the span’s inner content will depend on props.showInputEle‘s value.
    • If showInputEle‘s value is truthy, the <input> element will be the span’s inner content.
    • If showInputEle is falsy, the second <span> element will get rendered as the span’s inner content.
  4. Suppose showInputEle is falsy, and the second span element with the text “Joe Abraham” gets rendered in the browser. In that case, when you double-click the text, the span’s onDoubleClick event listener will trigger the handleDoubleClick function.
    Then, handleDoubleClick‘s invocation will update the state’s showInputEle property to true.
  5. As a result of the state update, React will automatically re-invoke App’s render() method.
    Consequently, render will trigger ElementMaker—which will check if showInputEle is truthy.
  6. Since showInputEle is now truthy, the <input> element will get set as the span’s inner content.
  7. Each time the user types into the text field, input element’s onChange listener will trigger handleChange. Then, handleChange will update the state’s fullName property with the user’s data.
  8. Once the user clicks out of the input field, onBlur will trigger handleBlur—which will update showInputEle to false.
  9. As a result of the state update, React will re-invoke App’s render() method.
  10. render() will trigger ElementMaker—which will check if showInputEle is truthy.
  11. Since showInputEle is now falsy, the span with the onDoubleClick attribute will get set as the first span’s inner content.

And there you have it! You’ve now seen how to click to edit elements in ReactJS!

Step 11: Run the Application

Take a look at your app in the browser by running:

npm start

Or, if your package manager is Yarn, run:

yarn start

You can also see my class component version here. Or check here if you prefer function components.

Wrapping It Up

Although this article used a simple React project to illustrate how you can double click to edit a web page’s text, the principles covered applies to any React application.

So, you can use the concepts you’ve learned to add validations or make images (or an entire webpage) editable on double click.

I hope you’ve found this article helpful. Thanks for reading.

Similar Posts