0

How can I render mobile and desktop specific assets within a component by calculating the page width. Seems like ternary expressions are the way by calculating window width but I'm running into issues.

Here is the condition:

If the window size is greater than lets say 500 - render the desktop component which as desktop specific assets.

Else, render the mobile component which has mobile specific assets.

Another case in this logic is if a video url has been provide this takes priority over the fallback image.

Here is what I have so far, I have a resize function to get the "window.innerWidth" and update state like so:

resize() {
        let windowWidth = window.innerWidth;

        this.setState({
            windowWidth: windowWidth
        })
    }

I pass the variable windowWidth as props to the component with the conditional logic.

Here is my logic so far:

render() {
        const {windowWidth, video, fallbackImage, mobileVideo, mobileImage, videoCallback, videoAnimationOffset} = this.props;
        return (
            <div className="hero-wrap col-xs-12 no-padding">
                {/* If video is available load otherwise render fallback image */}
                {video ? (
                    <div className="video-container">
                        <Video
                            video={video}
                            mobileVideo={mobileVideo}
                            videoCallback={videoCallback}
                            videoAnimationOffset={videoAnimationOffset}
                        />
                    </div>
                    ) : 
                    <div className="image-container" style={{backgroundImage: `url(${process.env.DB_URL}${fallbackImage})`}}>
                    </div> 
                }
            </div>
        )
    }

Here is maybe a concept of what I think could work but you can't nest ternary expressions:

{/* If window width is greater than 500 render desktop */}
{windowWidth > 500 ? 
    {video ? (
        <div className="video-container">
            <Video
                video={video}
                mobileVideo={mobileVideo}
                videoCallback={videoCallback}
                videoAnimationOffset={videoAnimationOffset}
            />
        </div>
        ) : 
        <div className="image-container" style={{backgroundImage: `url(${process.env.DB_URL}${fallbackImage})`}}>
        </div> 
    } : null 
}
Filth
  • 3,116
  • 14
  • 51
  • 79
  • What is the question? – WayneC Dec 15 '17 at 14:30
  • Any reason you can't use CSS media queries? This is exactly what they're for and they're quicker, more reliable and more responsive – Ben Kolya Mansley Dec 15 '17 at 14:32
  • 1
    I am using media queries but I don't want to render the desktop component at all on the page for initial load. – Filth Dec 15 '17 at 14:33
  • If he is trying to conditionally render a react component based on the window size he can't use css. – Dakota Dec 15 '17 at 14:33
  • 1
    If so, I'd recommend checking the user agent ( https://stackoverflow.com/a/11381730/4671195 ) for your initial test, then media queries to show/hide after – Ben Kolya Mansley Dec 15 '17 at 14:35
  • Also I think you should use the [clientwidth](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) instead of inner width. – Dakota Dec 15 '17 at 14:36
  • a library like [react-responsive](https://github.com/contra/react-responsive) should help – WayneC Dec 15 '17 at 14:43

2 Answers2

0

You could do something like the following to render the component dependent on your screen width value and whether the video prop is present :

renderMobile = () => {
  return (
   <img ... />
  )
}    

renderDesktop = () => {
 if(this.props.video) {
  return (
   <video ... />
  )
 } else {
  return(
   <img ... />
  )
 }
}

render() {
 return(
  (this.state.windowWidth > 500) ? this.renderDesktop() : this.renderMobile()
 )
}
craigo
  • 141
  • 1
  • 10
0

This seems working for me, can you check this?

return <div className="hero-wrap col-xs-12 no-padding">
  {
    windowWidth > 500 
    ? (video 
        ? <div className="video-container">
          <Video
              video={video}
              mobileVideo={mobileVideo}
              videoCallback={videoCallback}
              videoAnimationOffset={videoAnimationOffset}
          />
        </div>
      : <div className="image-container" style={{backgroundImage: `url(${process.env.DB_URL}${fallbackImage})`}}></div>) 
   : null
  }
</div>
Madhavan.V
  • 825
  • 1
  • 6
  • 14