9

I'm following the React Tutorial and got stuck on how to use React.findDOMNode.

Here is my code:

export class CommentForm extends React.Component<{}, {}> {
    handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        console.log(React.findDOMNode(this.refs['author']));
    }

    render() {
        return <form className="commentForm" onSubmit={ e => this.handleSubmit(e) }>
                 <input type="text" placeholder="Your name" ref="author" />
                 <input type="text" placeholder="Say something..." ref="text" />
                 <input type="submit" value="Post" />
               </form>;
    }
}

Calling console.log(React.findDOMNode(this.refs['author'])); gives me back <input type="text" data-reactid=".0.2.0" placeholder="Your name"> in the console. However, I cannot figure out how to retrieve the value of the input element (what I typed in the input box).

So far I've tried the following along with a few others:

React.findDOMNode(this.refs['author']).value; // "value" does not exist on type "Element"
React.findDOMNode(this.refs['author']).getAttribute('value'); // null
React.findDOMNode(this.refs['author']).textContent; // null

In intellisense I can see the following, but I still cannot figure out what to call here. enter image description here

I'm using the type definitions from DefinitedlyTyped. Also, I'm new to front-end development, so maybe my approach is wrong.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166

5 Answers5

12

Note that the tutorial is written in JavaScript, not TypeScript.

However, I have found the solution to doing this properly (OP's answer is very cumbersome). Basically, you have to make two changes from the tutorial code. For reference, here is the code from the tutorial as of me writing this:

var author = React.findDOMNode(this.refs.author).value.trim();

The first change is:

this.refs.author

Becomes

this.refs["author"]

I'm new to TypeScript, but I assume that it prefers you use indexer syntax over property syntax for objects that are meant to not have their true properties forward-declared.

Second, and most importantly,

React.findDOMNode

Becomes

React.findDOMNode<HTMLInputElement>

Basically here we have to specifically tell TypeScript what kind of element we are requesting. Use your code-complete to find a complete list of elements available. I assume it covers all intrinsic components.

Here is the final, working, line of code:

var author = React.findDOMNode<HTMLInputElement>(this.refs["author"]).value.trim();

For convenience, here is the completed method up to the point where this method first appears in the tutorial (slightly refactored to avoid invoking findDOMNode twice):

handleSubmit(e: React.FormEvent) {
    e.preventDefault();

    var authorInput = React.findDOMNode<HTMLInputElement>(this.refs["author"]);
    var textInput = React.findDOMNode<HTMLInputElement>(this.refs["text"]);

    var author = authorInput.value.trim();
    var text = textInput.value.trim();

    if (!text || !author)
        return;

    authorInput.value = textInput.value = "";
}
  • Thanks! I actually tried `HTMLElement` and a few other types, but they didn't work. I see now that to get `value` you have to use the `HTMLInputElement` interface. Knowing which type is a little tricky. – Jesse Good Oct 05 '15 at 03:11
  • I am using `React.findDOMNode` and getting `findDOMNode` does not exist on `'typeof _React'`. Any idea? – Yaniv Efraim Apr 10 '16 at 12:22
  • 3
    Answering myself... using `import * as ReactDOM from 'react-dom';` and then `ReactDOM.findDOMNode` solved my problem – Yaniv Efraim Apr 10 '16 at 12:25
6

I found this way to solve this issue.

const author = (ReactDOM.findDOMNode(this.refs.author) as HTMLInputElement).value;
drox2014
  • 93
  • 1
  • 5
  • Welcome to StackOverflow. Answers with only code in them tend to get flagged for deletion as they are "low quality". Please read the help section on answering questions then consider adding some commentary to your Answer. – Graham Mar 06 '18 at 15:12
0

References in React doesn't work like this. To get the DOM element of reference, you need to ask it in that way :

let authorElement = this.refs.author.getDOMNode();
gaelgillard
  • 2,483
  • 1
  • 14
  • 20
  • Hi, I tried out your example, but `getDOMNode` does not exist on `Component`. Here is the [declaration](https://github.com/borisyankov/DefinitelyTyped/blob/master/react/react.d.ts#L134). It does exist on `ClassicComponent` which I'm not using. – Jesse Good Sep 09 '15 at 23:54
  • This question is marked as TypeScript, not JavaScript. The .d.ts files included via tsd do not include a getDOMNode method. –  Oct 02 '15 at 20:19
0

EDIT: nlaq provided the answer to my question, however I think the following can be useful for readers, so I will leave this answer up.

After reading Forms | React article, I was able to acquire the value by handling the onChange event:

handleChange(e) {
    e.preventDefault();
    console.log(e.target.value); // e.target.value gives the value in the input box
}

render() {
    return <form className="commentForm" onSubmit={ e => this.handleSubmit(e) }>
             <input type="text" onChange={ e => this.handleChange(e) } placeholder="Your name" />
             <input type="text" placeholder="Say something..." ref="text" />
             <input type="submit" value="Post" />
           </form>;
}

I'm still puzzled why the tutorial showed the use of findDOMNode. Perhaps the tutorial is showing an old way? I'm still new to React, so if there is a more intuitive way please let me know.

For a full example, this SO answer helped me out.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • Check out my answer, it's presumably the proper way to handle this. The issue you're having is not because it's an old way of doing things, it's because TypeScript requires us to properly specify the type information. –  Oct 02 '15 at 20:05
0

None of the above solutions quite worked for me (and I think this might be a simpler solution). This is how I managed to get it to work in typescript (example using refs to focus the FormControl):

Make sure you've imported ReactDom:

import * as ReactDOM from 'react-dom';

In your component:

public focus():void {
    let input = ReactDOM.findDOMNode(this.refs["titleInput"]) as HTMLInputElement;
    input.focus();
}

render() {
    return (
        <FormGroup controlId="formBasicText">
            <FormControl ref={"titleInput"} type="text"/>
        </FormGroup>
    );
}
232 Studios
  • 105
  • 3
  • 12