Reputation: 1587
I have a parent component and a child component as following.
Parent component:
constructor(){
this.refs = React.createRef();
}
setRef(ref) {
console.log(ref)
}
handleChange(e) {
console.log(e)
}
render() {
return(
<ChildComponent ref={this.setRef} handleChange={this.handleChange.bind(this)}/>
)
}
Child Component:
render() {
return(
<input type="text" ref={this.props.ref} onChange={this.props.handleChange.bind(this)} > </input>
)
}
What changes should I do to get the ref
value inside the handleChange()
function in parent component? Thanks in advance.
Upvotes: 4
Views: 10509
Reputation:
If I´m reading correctly you want to access the input
element from the parent component?
You have to use another name for your prop as ref
is a keyword prop which will automatically assign the component the given variable.
<ChildComponent inputRef={this.setRef} handleChange={this.handleChange.bind(this)}/>
class ChildComponent extends Component {
render() {
return(
<input type="text" ref={this.props.inputRef} onChange= {this.props.handleChange.bind(this)} > </input>
);
}
}
Based on how you want to access the ref you can either set this.refs
directly to the prop or set it inside your setRef
function.
// either `this.refs` and then usable through `this.refs.current`
<ChildComponent inputRef={this.refs} {...} />
// or `this.setRef` and assign it yourself
setRef = (ref) => {this.refs = ref;}
Upvotes: 2
Reputation: 2343
ref
work only on native dom element, to make ref work on user defined Component, you need this:
https://reactjs.org/docs/forwarding-refs.html
Upvotes: 0
Reputation: 23753
ref
(as well as key
btw) is very special prop. It is not accessible in child by this.props.ref
.
Shortest way is to use different prop to pass ref
forward and backward:
class Parent ...
render() {
...
<Child inputRef={this.inputRef} />
class Child
...
render() {
<input ref={this.props.inputRef} ...
It's most flexible since you may access different ref
inside you child component(e.g. inputRef
+ scrollableContainerRef
+ popupRef
)
But in some cases you want to compose new component for existing code base. Say <input>
's replacement. Sure, in this case you would avoid changing all <input ref={...} />
onto <MyInput refProp={...}>
.
Here you may use React.forwardRef
. It feels the best with functional components like
export Child = React.forwardRef((props, forwardedRef) => {
...
return ...
<input ref={forwardedRef} />
})
But for class-based component you would rather use ref-prop
with different name:
class Child
...
render()
return
...
<input ref={this.props.forwardedRefName} />
export ChildWithForwardRef = React.forwardRef((props, ref) => <Child forwardedRefName={ref} {...props} />)
PS since you will consume what forwardRef
returns rather initial component(Child
) you may want to specify displayName
for it. This way you may be able find it later say with enzyme's find()
or easy recognize element in browser's React DevTools
Upvotes: 2