⚠️ This lesson is retired and might contain outdated information.

Use React ref to Get a Reference to Specific Components

Joe Maddalone
InstructorJoe Maddalone
Share this video with your friends

Social Share Links

Send Tweet
Published 11 years ago
Updated 2 years ago

When you are using React components you need to be able to access specific references to individual component instances. This is done by defining a ref. This lesson will introduce us to some of the nuances when using ref.

[00:00] Refs are a way for us to reference a node, or an instance of a component in our application. To get us started here, I'm creating a component that outputs a single input field. It's going to have an onchange event equal to this.update.bind to this. Right after, we're going to put out a bit of state, it's going to be this.state.a.

[00:24] We're going to go ahead and setup a constructor, we can create our initial state. We are going to call super to get our context, and we're going to set this.state equal to an object with a key of a, which is equal to an empty string. I'm going to go ahead and create our update method.

[00:41] We're going to follow a familiar pattern here, we're just going to take an event off of the input field, and we're going to call this.setState or a equal to the event target.value. It's going to be the value from our input field. We're going to save that, try it out in the browser, everything's going to work as expected when we type in the input field, it updates our state.

[01:06] Let's go ahead and say we wanted to have two of these guys, and drop in a horizontal rule just to break these up. On this one, we want it to update a state of b. Now, this isn't going to work with the existing pattern that we have in place, but we're just going to try it, we can see what happens. We're going to update our b with that value, as well.

[01:27] Now, when we type in the first field, the a field, it's updating both our a and our b state. Likewise, if we type in the b field, it's going to update our a and our b state. That's because we haven't differentiated between these two inputs.

[01:42] We can use a ref for that. On this guy, I'm going to say ref equals a, and on the second field, I'm going to say ref equals b, and that gives us a reference to each of these. I'm going to go ahead and kill off the event in our update method, and I'm going to set a to this.refs.a.value.

[02:01] Ref actually returns the node that we're referencing, here, I can say this.refs.b.value. Now, in the browser, when I type in the a field, it's updating our a state. When I type in the b field, it's updating our b state. The ref attribute or prop can also take a callback.

[02:23] Like I said before, it's returning the node or component that we're referencing, we get the node, we could take that, and here in our callback method, we could say this.a is equal to the node, and now for a, we can just call it, this.a. We get back that node, we can use the DOM method of value. Save that, and everything works as expected.

[02:46] We can also reference an instance of another component, here, let's create a quick component. We're going to call it input, we're going to return an input, and on this, we'll just have an onchange equal to this.propsUpdate.

[03:04] Up here, we're going to change this a input or input component, and now, since we're referencing a component, this is better represented by component rather than node. We'll say "component" there, and then, we're going to pass in this update, we don't need the type.

[03:24] Now, It's going to run that, and we're going to see that it's not exactly going to work. The b component is still working just fine, but here, a is no longer a node, it's now a component.

[03:38] One way we can get at that, is by bringing in ReactDOM, and then, wrapping this.a in ReactDOM.findDOMNode this.a, which is our component, and then, get the value off of that. Now, if we type in, here we get that value. The reason we're going to getting away with that is that, we are returning a single node here.

[04:03] When we get that component back, and we do findDOMNode on it, there's just one DOMNode there. But if we wrap this guy in a div, that findDOMNode call is referencing the div now, which has no value. One thing we could do, is put a ref on this guy, we'll call it input.

[04:22] Now, what we could do is, we can actually strip this back down, get rid of the ReactDOM find node part, and we could say, this.a which is our component.ref, we're getting the refs of our a component input, which is going to be that input field, and get its value.

[04:43] We save that, we type in our a field, we get our a. We type in our b field, we get our b.

Roman Liutikov
Roman Liutikov
~ 10 years ago

In your example each state has initial value of 0, but each slider initial value is 128 (since min=0, max=255 and the thumb is in the middle of the slider).

What is the way to initialize these in sync when using refs? Maybe there's a better approach?

Roman Liutikov
Roman Liutikov
~ 10 years ago

Ok, "Mixins" section already answered the question.

Pass initial value as a prop and use it with defaultValue prop.

Joel
Joel
~ 10 years ago

Are we dipping into the DOM 3x each time a single slider is adjusted? If so, any best practice advice for only querying the DOM element (slider) being adjusted? I can get it to work by binding this and the color to each Slider component, but it seems hacky: Slider ref="red" update={this.update.bind(this, "red")}

Chris
Chris
~ 9 years ago

I do not see the value in doing .getDOMNode vs, inp.getDOMNode.

León
León
~ 9 years ago

Am I the only one who see jQuery in this? I mean, "ref" depends on the structure of the HTML. If you change the hierarchy in the view it will fail

Joe Maddalone
Joe Maddaloneinstructor
~ 9 years ago

@León - it's not HTML, it's JSX which represents JS functions.

<Slider ref="red" update={this.update} />

is translated to:

React.createElement(Slider, { ref: "red", update: this.update })

Intellective Learning
Intellective Learning
~ 9 years ago

this stackoverflow answer says to avoid refs. Also the documentation sounds like refs are not ideal. Can this be built easily without using refs? Should refs actually be avoided? Why or why not?

Joe
Joe
~ 9 years ago

I think this video is out of date and the finished code is different than the code that is below, which took me some time to realize.

Inside the slider class you want to make sure the input element has a ref called "inp". Like this:

class Slider extends React.Component { render() { return ( <div> <input type="range" ref="inp" onChange={this.props.update} min="0" max="255" /> </div> ); } }

The App itself needs to pull the value like this:

ReactDOM.findDOMNode(this.refs.red.refs.inp).value

The whole update method looks like this:

update(e) { this.setState({ red: ReactDOM.findDOMNode(this.refs.red.refs.inp).value, green: ReactDOM.findDOMNode(this.refs.green.refs.inp).value, blue: ReactDOM.findDOMNode(this.refs.blue.refs.inp).value }); }

~ 9 years ago

Is anyone else getting this error in the update method? Uncaught ReferenceError: ReactDOM is not defined

I dont seem to be getting this though when calling ReactDOM.render at the bottom of App.js

Markdown supported.
Become a member to join the discussionEnroll Today