How to set ref to an unrendered element

2k views Asked by At

I have a login page where I'm placing a button "Watch the video". On click of the button, I'm hiding the button and displaying a video. Now my requirement is to start playing the video as soon as it displays without having to click the play button. I'm trying to use refs and somehow I'm unable to set the ref to my video element. Is there any way to set the refs to unrendered elements in componentDidUpdate? Please help me! Following is my code

export default class NewLoginPage extends Component {
  constructor(props) {
    this.vidRef = React.createRef();
    this.state = {
      showVideo: false
    };
  }
    
  handleVideoClick = () => {
    this.setState({ showVideo: true })
    this.vidRef.current.play();
  }
    
  handleCloseClick = () =>{
    this.setState({ showVideo: false })
  }
    
  render() {
    let language_labels = labels["english_labels"]
    console.log(labels)
    console.log(language_labels)
    return (
      <div className="container-fluid no-padding">
        <div className="new-login-div">
          <AppBar className="app-bar">
            <Toolbar className="tool-bar">
              <img src={pmiLogo} />
              {/* <NavLink to="/" id="invoice_upload">LOG OUT</NavLink> */}
              {/* <Button className="logout-btn">REGISTER</Button> */}
            </Toolbar>
          </AppBar>
          <Grid container>
            <Grid item xs={4}>
              <h1 className="welcome-heading">Self Service Portal</h1>
              <TextField
                className="id-field"
                placeholder="Email"
                inputProps={{
                  style: {
                    color: "#fff",
                    paddingLeft: "5px"
                  }
                }}
              />
              <br />
              <Button className="login-btn" endIcon={<ArrowForwardIcon />}>Log In</Button>
            </Grid>
            <Grid item xs={8}>
              <div className="video-div">
                {this.state.showVideo && <div>
                 <IconButton className="close-btn" onClick={(event) => this.handleCloseClick()}>
                   <CloseIcon />
                 </IconButton>
                 <video ref={ref => { this.vidRef = ref }} width="500" height="285" controls className="video-container">
                   <source src={exampleVid} type="video/mp4" />
                   Your browser does not support the video tag.
                 </video>
               </div>}
               {!this.state.showVideo && <div className="intro-div">
                 <h5 className="intro-text">
                   Supporting the vitality and survival of US small businesses—who employ nearly half of the American workforce—is especially critical now. Let’s not forget just how essential they are.
                 </h5>
                 <Button
                   disableRipple={true}
                   className="video-button"
                   startIcon={<PlayArrowIcon className="play-icon" />}
                   onClick={(event) => this.handleVideoClick()}
                 >
                   Watch video
                 </Button>
                 <br />
                 <Button
                   disableRipple={true}
                   className="reg-button"
                   startIcon={<ChevronRightIcon className="play-icon" />}>
                   Register
                 </Button>
               </div>}
             </div>
           </Grid>
         </Grid>
       </div>
     </div>
   );
  }
}
2

There are 2 answers

0
Anton Bakinowsky On

React ref property is used to access DOM element reference.
If element is not rendered then DOM element is not created (deleted).
Thus you can't get a ref of something that doesn't exist.

0
Mr. N On

You don't need to use a ref to do that, you can add the autoplay html property to your <video> for details on autoplay

You can't make use of a ref to an element that is not yet rendered as Anton explained in his answer, the ref.current will be null.

However, it is suggested that you create a separate component for the video and it's logic from that of the login, not only it will solve the issue (the this.state.showVideo condition will stay in the parent component) but it is also how React components should be, for more details refer to this.