10

I am new in the React world and was learning about Refs. The React doc says that:

Refs provide a way to access DOM nodes or React elements created in the render method.

I think that we can do the same thing with the querySelector function.
The React doc gives an example of how can we use Refs to focus on the input element.
Here's the code ->

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // create a ref to store the textInput DOM element
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // Explicitly focus the text input using the raw DOM API
    // Note: we're accessing "current" to get the DOM node
    this.textInput.current.focus();
  }

  render() {
    // tell React that we want to associate the <input> ref
    // with the `textInput` that we created in the constructor
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Doing the same thing with querySelector ->

class CustomTextInput extends React.Component {
constructor(props) {
    super(props);
    this.textInput = React.createRef();
  }

  focusTextInput = () => {
    const input = document.querySelector("input");
    input.focus();
  };

  render() {
    return (
      <div>
        <input type="text" ref={this.textInput} />
        <button type="button" onClick={this.focusTextInput}>
          Focus the Text Input
        </button>
      </div>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Boann
  • 48,794
  • 16
  • 117
  • 146
Yogesh Tripathi
  • 703
  • 5
  • 16
  • 2
    Suppose there's more than one input in the document. How do you know your querySelector returns the correct one? What if your component is used more than once in the same view? – ray Jun 14 '20 at 18:24
  • 1
    @rayhatfield we can add id to the input – Yogesh Tripathi Jun 14 '20 at 18:25
  • 2
    Important NOTE: `.querySelector` --> returns the first Element within the document that matches the specified selector, or group of selectors. `.querySelectorAll()` --> returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors. – dale landry Jun 14 '20 at 18:25
  • 1
    @dalelandry what if i add id in the element and use getElementById – Yogesh Tripathi Jun 14 '20 at 18:26
  • 1
    As with everything else, there are many ways to accomplish the same thing. So you can get into the business of generating IDs for every element if you want. Or you could just keep a reference to the current instance's element using a ref. The ref is going to be easier and less error-prone, but if you want to use a querySelector by all means knock yourself out. – ray Jun 14 '20 at 18:27
  • getElementById, will get the specific element with that ID, it is focusing on that ID only as ID is a unique identifier. However, if you are looping over a list of nodes like an input to find a value, you could then use 'qeurySelectorAll()` and select the tag or class depending on what logic your code needs to implement. – dale landry Jun 14 '20 at 18:28
  • 1
    If you are going to work with React you are best to forget that methods like `querySelector()` even exist. Let React worry about the dom and you only interact with it's state – charlietfl Jun 14 '20 at 18:32
  • @dalelandry I just wanted to know whether using querySelector or querySelectorAll will be bad idea in react. My question may be stupid. i don't know much about react. – Yogesh Tripathi Jun 14 '20 at 18:32
  • 1
    In general...yes it is a bad idea. – charlietfl Jun 14 '20 at 18:32
  • 1
    What is the reason ? – Yogesh Tripathi Jun 14 '20 at 18:33
  • As seen on MDN documentation...`element = document.querySelector(selectors);` and` elementList = parentNode.querySelectorAll(selectors);`... querySelector -> "The matching is done using depth-first pre-order traversal of the document's nodes starting with the first element in the document's markup and iterating through sequential nodes by order of the number of child nodes." `querySelectorAll()` -> "This method is implemented based on the ParentNode mixin's querySelectorAll() method." Also, the selector string must be a valid CSS selector string. – dale landry Jun 14 '20 at 18:36
  • I agree with charlietfi in that you should use the built in methods within React for their methods – dale landry Jun 14 '20 at 18:38
  • 2
    `querySelector()` search among all html elements to find the target element but by using `ref` you have access directly to the element. additionally, the element that you are looking for may change, for example its `cssClass` may be removed and you won't be able to find it anymore. – Ehsan Nazeri Jun 14 '20 at 18:41
  • Thanks for the reply all of you!. As you all are more experienced than me, I would choose to agree with your points. However I still don't get the solid reason of using Refs. May be it is just doing the same thing with different ways. – Yogesh Tripathi Jun 14 '20 at 18:41
  • 2
    Over simplification of reason is that React replaces existing elements in dom as state changes and although they look the same and have same properties they are not the exact same element object each time. React does this under the hood and what you should focus on is the state and not the dom – charlietfl Jun 14 '20 at 18:41
  • 1
    Why use React at all? You can achieve everything React does using plain javascript, of course, because that's all React is. – ray Jun 14 '20 at 18:57
  • i have tried to answer it here https://stackoverflow.com/a/69260293/2054671 – gaurav5430 Sep 20 '21 at 20:28

2 Answers2

2

Since, the framework itself has exposed a method to do something which can be done through vanilla javascript, it certainly has added advantages. One of the scenario I can think of is using React.forwardRef which can be used for:

  • Forwarding refs to DOM components
  • Forwarding refs in higher-order-components

As explained in the React docs itself:

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
sonali
  • 37
  • 3
  • what if your looping generating the buttons, I have a unique ID I can assign to ref, not sure how that works here. – gunslingor Apr 26 '23 at 22:00
1

you don't need react or angular to do any web development, angular and react give us a wrapper which will try to give us optimize reusable component, all the component we are developing using react can be done by web-component but older browser don't support this.

i am listing some of benefit of using ref in React

  1. this will be helpful for if you are using server side rendering, Be careful when you use Web API(s) since they won’t work on server-side Ex, document, Window, localStorage
  2. you can easily listen to changes in state of object, you don't have to maintain or query the DOM again and again and the framework will do this for you.
Lightning
  • 386
  • 3
  • 15
Jadli
  • 858
  • 1
  • 9
  • 17