Author avatar

Gaurav Singhal

How to Use React.findDOMNode in TypeScript

Gaurav Singhal

  • Aug 10, 2020
  • 6 Min read
  • 214 Views
  • Aug 10, 2020
  • 6 Min read
  • 214 Views
Web Development
Front End Web Development
Client-side Framework
React

Introduction

Any web app involves extensive use of forms, and working with forms requires you to read DOM values, such as from an input field. These values can either be stored in the state, validated on the frontend, or sent to the server. In such situations, React allows you to use a method called React.findDOMNode(), which returns a native browser DOM element. However, using it in TypeScript requires some additional changes to the standard code.

This guide will show you how to correctly use React.findDOMNode() in a React and TypeScript app to extract values from a DOM element.

Setting up the React Typescript App

Create an empty TypeScript project in React by running the following command:

1
npx create-react-app react-dom-ts --typescript
shell

Then create a simple Form component called Form.tsx.

1
2
3
4
5
6
7
8
import React from 'react';

export class Form extends React.Component<{},{}> {
    
    render() {
        return <h1>Inside Form Comp</h1>;    
    	}
}
tsx

The above component simply renders some text. Add the interface for state and props and pass them to the class declaration of the form component. The state contains a single property name of type string .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';

interface State{
    name:String
}

interface Props{
    
}

export class Form extends React.Component<Props,State> {

    render() {
        return <h1>Inside Form Comp</h1>;        
    }
}
tsx

Initialize the state inside the constructor.

1
2
3
4
5
6
 constructor(props: Props){
        super(props);
        this.state={
            name:''
        }
    }
tsx

So far, your form component's boilerplate is ready.

Creating the Form Template

Now that boilerplate is ready, next add a form inside the render() method of the form component that contains an input field and a submit button. To get a reference to the input, assign a ref attribute to the field as demonstrated below.

1
2
3
4
5
6
7
8
9
10
render() {
  
    return 
    <form className="commentForm">
        <input type="text" placeholder="Your name" ref="name" />
        <button type="submit" >Submit</button>
        {this.state.name}
    </form>;

}
tsx

Also, add an onSubmit event to the form to listen to submit events on the form.

1
2
3
...
 return <form className="commentForm" onSubmit={ e => this.handleSubmit(e) }>
...
jsx

Now all DOM manipulations can be done inside the handleSubmit() method. This method takes the event object as a parameter of type React.FormEvent. Call the e.preventDefault() method to prevent the default submit action of reloading the page.

1
2
3
handleSubmit(e: React.FormEvent) {
    e.preventDefault();
}
tsx

Using React.findDOMNode() in TypeScript

To get the input DOM element, use the ReactDOM.findDOMNode() method by passing in the reference object of the DOM element as a parameter. In class components, your references can be accessed by calling this.refs and passing the name of the ref in square brackets. You can relate this to accessing a key in an object using bracket notation. Consider the following line of code:

1
let input = ReactDOM.findDOMNode(this.refs["name"])
jsx

ReactDOM.findDOMNode() returns the entire input element and stores it inside input, which is a local variable. If you were to write the above line of code in JavaScript, everything would work as intended. However, in TypeScript, you must also specify the type of element requested. Since it returns a DOM node of type HTMLInputElement, you must specify it using the as keyword. Hence the above line of code becomes

1
let input = ReactDOM.findDOMNode(this.refs["name"]) as HTMLInputElement;    
tsx

Now the input variable stores the entire input DOM node. To get the value entered in this field, call the value property on this element and store it inside the state.

1
2
3
4
5
6
7
8
    handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        let input = ReactDOM.findDOMNode(this.refs["name"]) as HTMLInputElement;    
        console.log(input.value)
        this.setState({
            name:input.value
        })
    }
tsx

Final Code

Let's combine all the above code snippets. See the final code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import React from 'react';
import * as ReactDOM from 'react-dom'

interface State{
    name:String
}
interface Props{

}
export class Form extends React.Component<Props, State> {
    constructor(props: Props){
        super(props);
        this.state={
            name:''
        }
    }
    handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        let input = ReactDOM.findDOMNode(this.refs["name"]) as HTMLInputElement;    
        console.log(input.value)
        this.setState({
            name:input.value
        })
    }


    render() {
        return <form className="commentForm" onSubmit={ e => this.handleSubmit(e) }>
                 <input type="text" placeholder="Your name" ref="name" />
                 <button type="submit" >Submit</button>
                 {this.state.name}
               </form>;
    }
}
tsx

Finally, remember to render your Form component inside App.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react';
import './App.css';
import { Form } from './Home';

function App() {
  return (
    <div className="App">
      <Form/>
    </div>
  );
}

export default App;
tsx

If you type anything inside the input field and click the submit button, you will see the value of the field logged out on the console as well as on the page. This validates that you successfully captured the input field's value using React.findDOMNode() and stored it inside your component's state.

Conclusion

Simply attaching a ref callback to a particular DOM node should get you through all your required DOM manipulations smoothly. findDOMNode is more of a trick that you can use to access DOM elements. If you call it on a component that isn't created or mounted on the DOM yet, or a functional component, an exception will be thrown. React's official documentationclearly says to avoid using it since abstracts away from React's component architecture. A practical situation where you can use it is when your target ref is a component itself.

0