I want to use ref, however I am not able to use this in the conditional rendering which is initially false.
constructor(props) {
super(props);
this.state = {
filterActive: false,
}
this.firstRef = React.createRef();
}
If I use ref in this :-
{this.state.filterActive ?
<label ref={this.firstRef}>Time Range</label>
:null}
The ref is null.
I want to use ref, however I am not able to use this in the conditional rendering which is initially false.
constructor(props) {
super(props);
this.state = {
filterActive: false,
}
this.firstRef = React.createRef();
}
If I use ref in this :-
{this.state.filterActive ?
<label ref={this.firstRef}>Time Range</label>
:null}
The ref is null.
Share Improve this question asked Sep 25, 2019 at 9:22 Anup MishraAnup Mishra 1491 gold badge2 silver badges12 bronze badges 5-
Not an answer, but you can rewrite your code as
{this.state.filterActive && <label ref={this.firstRef}>Time Range</label>}
- no need for the ternary operator returningnull
if false. – James Whiteley Commented Sep 25, 2019 at 9:24 - Hi @JamesWhiteley many thanks for your help. Actually this is just a dummy. I have a full section which needs to be rendered conditionally. Inside that section there are many elements and I want to use ref in one of those element. – Anup Mishra Commented Sep 25, 2019 at 9:27
-
When are you making
filterActive
state to true? Please share that code also. – Rinkesh Golwala Commented Sep 25, 2019 at 9:27 - on click of a button @RinkeshGolwala – Anup Mishra Commented Sep 25, 2019 at 9:28
- Please share the plete ponent. – Rinkesh Golwala Commented Sep 25, 2019 at 9:29
3 Answers
Reset to default 4How about something Like this:
// directly assign the element to this.firstRef
// instead of doing it in the constructor
<label
ref={(elem) => (this.firstRef = elem)}
style={{display: this.state.filterActive ? 'inline-block' : 'none'}}
>
Time Range
</label>
and when using this.firstRef you put you work inside an if like this:
if (this.firstRef) {
// your work
}
I was facing the same problem but I'm using hooks. I found an alternate solution. By using Intersection Observer, we can solve it.
In Hooks, use 'useInView' hook from 'react-intersection-oberserver',
// Use object destructing, so you don't need to remember the exact order
const { ref, inView, entry } = useInView(options);
// Or array destructing, making it easy to customize the field names
const [ref, inView, entry] = useInView(options);
Attach 'ref' to your DOM node, 'inView' will return a boolean whether your DOM node is in View or not and 'entry' will give access to DOM node properties.
import React from 'react';
import { useInView } from 'react-intersection-observer';
const Component = () => {
const { ref, inView, entry } = useInView({
/* Optional options */
threshold: 0,
});
return (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
);
};
This fixed my problem.
For class based ponents, read here: https://developer.mozilla/en-US/docs/Web/API/Intersection_Observer_API
try this,
render(){
return(
{this.state.filterActive ? (<label ref={this.firstRef}>Time Range</label>) : (null)}
)}