Ref returns null, but it isn't(null)?

Ref returns null, but it isn't(null)?
0

I’m trying to make a react video player.
Video gets loaded fine, when i press play, it gets played and so on.
Trouble occurs when i want to display duration of it.
I tried accessing it via ref. It gets video, but ref returns null? I’m console logging and in it, amongst other properties is duration.
Here’s an image of:


To add: I’m calling ref in componentDidMount() just to see if it’s being ‘catched’.

Here is the code:

import React from 'react';
import ReactDOM from 'react-dom';

class Show extends React.Component {
    
    constructor(props) {

        super(props);
        this.state = {
            video: "",
            switch: false,
            remaining: null,
        };
        this.playPause = this.playPause.bind(this);
        this.videoRef = React.createRef();
        this.trackTime = this.trackTime.bind(this);
        this.volume = this.volume.bind(this);
        this.fullScreen = this.fullScreen.bind(this);

    }

    fullScreen(){

        let elem = this.videoRef.current;
        if (elem.requestFullscreen){
            elem.requestFullscreen();
          } 
          else if (elem.mozRequestFullScreen){ /* Firefox */
            elem.mozRequestFullScreen();
          } 
          else if (elem.webkitRequestFullscreen){ /* Chrome, Safari & Opera */
            elem.webkitRequestFullscreen();
          } 
          else if (elem.msRequestFullscreen){ /* IE/Edge */
            elem.msRequestFullscreen();
          }

    }

    volume(e){
        this.videoRef.current.volume = e.target.value/100;
    }

    trackTime(e){
        this.setState({
            remaining: e.target.duration - e.target.currentTime,
        });
    }

    playPause(){

        this.setState({
            switch: !this.state.switch
        });
        
        if(this.videoRef.current.paused){
            this.videoRef.current.play();
        }
        else{
            this.videoRef.current.pause();
        }

    }

    componentDidMount(){

        let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
        
        let urlId = window.location.href;
        let getaVideoIdId = urlId.lastIndexOf("/");
        let videoId = urlId.substring(getaVideoIdId+1, urlId.length);
        
        $.ajax({
            url: '/showAjax',
            type: 'POST',
            data: {_token: token , message: "bravo", videoId: videoId},
            dataType: 'JSON',
            success: (response) => { 
                console.log("success");
                //console.log(response);
                this.setState({
                    video: response.video,
                }); 
                
            },
            error: (response) => {
                console.log("error");
                console.log(response);
            }
        }); 
        console.log(this.videoRef);
        //this.videoRef.current.play();
    }

    render(){
        //console.log(this.state);
        
        let PlayPause = this.state.switch ? "fa fa-pause-circle" : "fa fa-play-circle";

        let minutes = Math.floor(this.state.remaining/60);
        minutes = (""+minutes).length===1 ? "0"+minutes : minutes;//Checks if mins are one digit by turning it into string that now beasues length, if length is 1(single digit), if it is, then adds zero in front of it.
        let seconds = Math.floor(this.state.remaining%60);
        seconds = (""+seconds).length===1 ? "0"+seconds : seconds;//Same as mins, but for seconds.
        let remainingTime = minutes+" : "+seconds;

        let videoUrl = this.state.video && this.state.video.name ? "/storage/"+this.state.video.user.name+"'s Videos/"+this.state.video.name : null;

        let video = videoUrl ? <div  className={"videoWrapper"}><video ref={this.videoRef} preload="auto" onTimeUpdate={this.trackTime}>
            <source src={videoUrl} type="video/mp4"/>
            <source src={videoUrl} type="video/ogg"/>
            Your browser does not support the video tag.
            </video>
            <div id="controls">
                
                <button className="btnV" onClick={this.playPause}><i className={PlayPause}></i></button>
                <div className="time">{remainingTime}</div>
                <input type="range" className="custom-range" id="customRange" name="points1" onChange={this.volume}/>
                <div className="time" onClick={this.fullScreen}><i className="fa fa-expand"></i></div>
            
            </div>
        </div> : "";
       
        return (
            <div className="container">
                {video}
            </div>
        );
    
    }

}

if(document.getElementById('show')){

    ReactDOM.render(<Show/>, document.getElementById('show'));

}

$.ajax function is asynchronous.
console.log(this.videoRef); is executed before the ajax function finish fetching data.
and since you render the video element only if videoUrl is not undefined, your ref is undefined.
if you remove the condition that render the video element it should works.

I know that. Problem is inconsistency. In my pomodoro project, calling this.audioRef.current.play() made sound play. This don’t work here. Or if i check duration with this.videoRef.current.duration, throws a NaN.

it depend on where you put this code. if you check the duration in componentDidMount() you get NAN the video is not loaded yet.
if you check it in componentDidUpdate() it will works

It isn’t panacea. It works only if video gets played first. Then getting duration will show actual number. Which is same as clicking. I need to get duration before that, before “proverbial” click.