Ruchi Ray
Ruchi Ray

Reputation: 257

I want to select the text inside input box by clicking on a button in react js but my code doesn't work

when i click on the focus button , i want to change the text inside the input box and then select it. But i have to click on the button twice to accomplish this task, that is, when i first click on the button , only the value is changed and when i click again, then the the text is selected

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

export default function App() {
  const [name, setName] = useState('')
  const inputRef = useRef();
  const editItem = () => {
    setName('ray')
    inputRef.current.select();
  };
  return (
    <>
      <input
        ref={inputRef}
        type="text"
        value={name}
        placeholder="e.g. eggs"
        onChange={(e)=>setName(e.target.value)}
      />
      <button type="button" className="edit-btn" onClick={editItem}>
        Focus
      </button>
    </>
  );
}

Upvotes: 2

Views: 1597

Answers (3)

Akhilesh
Akhilesh

Reputation: 524

You can use useEffect hook to trigger the text selection. Toggle a focus variable, whenever the focus button is clicked. So, on every click the text gets selected.

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

export default function App() {
  const [name, setName] = useState("");
  const [focus, setFocus] = useState(false);
  const inputRef = useRef();
  useEffect(() => {
    inputRef.current.select();
  }, [focus]);
  const editItem = () => {
    setName("ray");
    setFocus(!focus);
  };
  return (
    <>
      <input
        ref={inputRef}
        type="text"
        value={name}
        placeholder="e.g. eggs"
        onChange={(e) => setName(e.target.value)}
      />
      <button type="button" className="edit-btn" onClick={editItem}>
        Focus
      </button>
    </>
  );
}

Upvotes: 2

Dogu Deniz Ugur
Dogu Deniz Ugur

Reputation: 329

setName() is an asynchronous function which means when you first click the button inputRef.current.select(); is executed before setName() is finished. As a solution you can do:

const editItem = () => {
    setName('ray')
  };

useEffect(()=>
  {
    inputRef.current.select();
  },[name]);

This calls inputRef.current.select() as soon as setName() changes the state.

Upvotes: 1

Charchit Kapoor
Charchit Kapoor

Reputation: 9294

You should useEffect hook to select the text, because state changes in React are asynchronous. Try like this:

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

export default function App() {
  const [name, setName] = useState("");
  const inputRef = useRef();
  const editItem = () => {
    setName("ray");
  };

  useEffect(() => {
    if (name === "ray") {
      inputRef.current.select();
    }
  }, [name]);
  return (
    <>
      <input
        ref={inputRef}
        type="text"
        value={name}
        placeholder="e.g. eggs"
        onChange={(e) => setName(e.target.value)}
      />
      <button type="button" className="edit-btn" onClick={editItem}>
        Focus
      </button>
    </>
  );
}

The useEffect here executes everytime when name state is changed and selects the text if it is ray, because that's what button click sets it to.

To learn more about useEffect, check this link. Check this code working here.

Upvotes: 1

Related Questions