ReactJS - How to autofocus an element with contentEditable attribute true in ReactJs class component?

Viewed 183

I found this p tag in a project I'm working on. This serves as an input field in my front end. I'm not that familiar p tag's being an input field, but I'd just to have the textfocus automatically in this p tag input field when my components loads, so a user is always ready to type and knows where to type.

      <div className="create-post">
        <p
          contentEditable={!this.props.isLoading}
          spellCheck="true"
          placeholder="Write a new post here"
          id="txtContent"
          onKeyUp={this.entSub}
          onDrop={this.dropDrag}
        ></p>
      </div>

I tried just adding autoFocus as prop to the P tag, but nothing happens. I guess that works only in the real HTML input field.

2 Answers

You will need to use refs (useRef hook) & then simply inputRef.current.focus();.

Tricky part is how to move the caret to the end?

const textLength = inputRef.current.innerText.length;
const range = document.createRange();
const sel = window.getSelection();

range.setStart(inputRef.current.childNodes[0], textLength)
range.collapse(true)

sel.removeAllRanges()
sel.addRange(range)

Full code

import React, { useRef, useEffect } from "react";
import "./styles.css";

export default function App() {
  const inputRef = useRef(null);
  useEffect(() => {
    inputRef.current.focus();
    // move caret to end
    const textLength = inputRef.current.innerText.length;
    const range = document.createRange();
    const sel = window.getSelection();

    range.setStart(inputRef.current.childNodes[0], textLength)
    range.collapse(true)
    
    sel.removeAllRanges()
    sel.addRange(range)

  }, [inputRef]);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <div className="create-post">
        <p
          contentEditable
          spellCheck="true"
          placeholder="Write a new post here"
          id="txtContent"
          ref={inputRef}
        >
          Content Editable
        </p>
      </div>
    </div>
  );
}

Complete example on Codesandbox

See comments for explanation, and please ask if you have any questions.

Also note, you may have more luck with a span or div tag than a p tag when it comes to contentEditable. Behavior may vary across browsers.

export class App extends React.Component {
  constructor(props) {
    super(props);
    this.editableRef = React.createRef(); // Create a ref
  }

  componentDidMount() {
    this.editableRef.current.focus(); // Runs only on mount to focus the element
  }

  render() {
    return (
      <div className="create-post">
        <p
          ref={this.editableRef} // Assign ref to your element
          contentEditable={!this.props.isLoading}
          spellCheck="true"
          placeholder="Write a new post here"
          id="txtContent"
          onKeyUp={this.entSub}
          onDrop={this.dropDrag}
        />
      </div>
    );
  }
}

Related