React local video does not load in production - reactjs

I am trying to loop a very simple video contained in src/Assets/videos.
When I deploy a local server with npm start, the video performs as expected, however, when I publish to production the video does not load. I am using AWS Amplify CLI to publish the app.
I tried to:
1). View the app in a different browser (Firefox and Chrome).
2). Load the video from /public via an environment variable.
3). Load the video via the react-player module.
My initial code was home.js component rendered in app.js:
import heroVideo from '../../Assets/videos/heroVid.mp4';
//...
export default function HomePage() {
return (
<div id="hero" align="center" className="center">
<div>
<video muted autostart autoPlay loop >
<source src={heroVideo} type="video/mp4"/>
Your browser does not support the video tag.
</video>
</div>
<div style={{width: '90%'}}>
<div>
<img src={logo} style={{height: '200px', borderRadius: '100px'}} className={classes.blue} alt={`${props.brandName} Logo`}/>
<h4>A QC HOME BUYERS COMPANY</h4>
<h1>QC General Contractors</h1>
<h2 className="script">Let's build your future together</h2>
<NavLink to="/request-quote" className="simple-link"><Button variant="contained" color="secondary">Request a quote</Button></NavLink>
</div>
</div>
</div>
)
}
Then I tried to load from /public:
export default function HomePage() {
return (
<div id="hero" align="center" className="center">
<div>
<video src={process.env.PUBLIC_URL + 'Videos/heroVid.mp4} muted autostart autoPlay loop />
</div>
<div style={{width: '90%'}}>
<div>
<img src={logo} style={{height: '200px', borderRadius: '100px'}} className={classes.blue} alt={`${props.brandName} Logo`}/>
<h4>A QC HOME BUYERS COMPANY</h4>
<h1>QC General Contractors</h1>
<h2 className="script">Let's build your future together</h2>
<NavLink to="/request-quote" className="simple-link"><Button variant="contained" color="secondary">Request a quote</Button></NavLink>
</div>
</div>
</div>
)
}
Finally react-player:
import heroVideo from '../../Assets/videos/heroVid.mp4';
import ReactPlayer from 'react-player'
//...
export default function HomePage() {
return (
<div id="hero" align="center" className="center">
<div>
<ReactPlayer url={heroVideo} loop="true" volume="0" muted="true" playing="true" style={{height: "100%"}} />
</div>
<div style={{width: '90%'}}>
<div>
<img src={logo} style={{height: '200px', borderRadius: '100px'}} className={classes.blue} alt={`${props.brandName} Logo`}/>
<h4>A QC HOME BUYERS COMPANY</h4>
<h1>QC General Contractors</h1>
<h2 className="script">Let's build your future together</h2>
<NavLink to="/request-quote" className="simple-link"><Button variant="contained" color="secondary">Request a quote</Button></NavLink>
</div>
</div>
</div>
)
}
I am still relatively new to react and AWS Amplify - Is there something I am missing?
Thanks in advance for any guidance.

Have you modified your rewrite rules to add mp4 ?
</^[^.]+$|\.(?!(css|mp4|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>

I was having the same issue as well, the easiest solution I found was to create an S3 bucket on AWS and upload the video file there and grab the src from said video. You're also gonna have to add public read access for your bucket/object.

Did #jsc31994 recommendation :
Uploaded the video on a S3 bucket and then used ReactPlayer
<ReactPlayer
url='https://xxx.s3.us-east-2.amazonaws.com/xxx-background.mp4'
playing={true}
loop={true}
muted={true}
controls={false}
id="background_video"
/>

Related

Video isn't playing in my React app when trying to import a video component and html video tag

I'm trying to import a video to my JSX but the video doesn't seem to play, it acts like an image.
Here's what I've tried:
import React from "react";
import MyVideoComponent from "./MyVideoComponent";
const Video = () => {
return (
<div className="w-full max-w-[800px] sm:h-[704px] h-[680px] bg-white flex flex-col sm:justify-between justify-center items-center mx-auto p-4">
<div>
<div className="h-[10%] flex items-center relative">
<div className="h-[100%] w-[8%] bg-gray-200"></div>
<div className="flex items-center">
<h5 className="text-sm py-2 text-[#575e72] font-mono left-9 absolute">
VIDEO TITLE
</h5>
</div>
</div>
<div className="my-5 py-4 px-1 w-[80%]">
<h1 className="text-4xl font-bold text-[#061237]">
Inform users with video sections
</h1>
</div>
<div>
<MyVideoComponent />
</div>
</div>
</div>
);
};
export default Video;
MyVideoComponent:
import React from "react";
import MyVideo from "../assets/video.mp4";
class MyVideoComponent extends React.Component {
render() {
return (
<video width="100%" height="100%" preload="auto">
<source src={MyVideo} type="video/mp4" />
Your browser does not support HTML5 video.
</video>
);
}
}
export default MyVideoComponent;
I've also tried using the code below instead of importing MyVideoComponent component
<video width="auto" height="auto" autoplay>
<source src={require('../assets/video.mp4')} />
</video>
This is common problem when you deal with html5 tag in react. You need toJust set a name for the autoplay attribute or use autoPlay. In addition, set the muted tag for the video. Chrome for instance block autoplay videos that have sound.
The code structure should look like this

How to fix unexpected behavior of Next/Link when it is a child of a button?

I am experiencing some issues with next/link when I use it in my app.
I have a reusable component that renders a button. This component is used twice on the page with different urls each time.
When the page is in desktop view, the button works perfectly. I can navigate from one page to another. When I reduce the size of the screen to either tablet or mobile one redirects correctly and the other one does not respond as expected.
To work around the issue I have enclosed the area inside a link so the user can click outside the button area and still be directed to the page but it is not really the experience I want to offer to the user.
I never had this before. Can someone tell me how to fix this or why is it behaving this way, please? thanks.
const Banner = ({
purpose,
imageUrl,
title1,
title2,
desc1,
linkName,
buttonText,
}) => {
return (
<div className="row flex-lg-row-reverse align-items-center g-5 justify-content-center">
<div className=" col-10 col-sm-8 col-lg-6">
<Image
className="d-block img-fluid mx-lg-auto"
src={imageUrl}
width={700}
height={500}
alt="banner"
loader={myLoader}
/>
</div>
<Link href={linkName} passHref>
<div className="col-lg-4 p-3 text-center text-lg-start border-0">
<h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
<p className="lead">
{title1}
<br /> {title2}
</p>
<p className="lead">{desc1}</p>
<button className="btn link btn-primary btn-xl w-100">
<Link href={linkName} passHref>
<a> {buttonText}</a>
</Link>
</button>
</div>
</Link>
</div>
);
};
export default function Home({ data }) {
const {
results: {
client: { secondhandListing },
},
} = data;
//console.log('index page results',secondhandListing);
return (
<>
<div
data-spy="scroll"
data-bs-target="main-nav"
data-offset="0"
className="scrollspy-example"
tabIndex="0"
>
<Services />
<div className="section d-flex justify-content-center my-5">
<h1 className="my-5" id="#scrollspyHeading2">
Properties
</h1>
</div>
<div className="container-fluid d-flex justify-content-xxl-between align-items-center flex-wrap flex-lg-nowrap">
<div className="section d-flex">
<Banner
purpose="Rent a Home"
title1="Rental Homes for"
title2="Everyone"
desc1="Explore Apartments, Villas, Homes"
desc2="and more"
buttonText="Explore Renting"
linkName="/search?operationType=rent"
imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
/>
</div>
<div className="section d-flex">
<Banner
purpose="Buy a Home"
title1="Find, Buy & Own"
title2="Your Dream Home"
desc1="Explore Apartments, Villas, Homes"
desc2="and more"
buttonText="Explore Buying"
linkName="/search?operationType=sale"
imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
/>
</div>
</div>
<Team />
<Contact />
</div>
</>
);
}
Run the new-link codemod to automatically upgrade previous versions of Next.js to the new <Link> usage:
npx #next/codemod new-link .
This will change <Link><a id="link">Home<a></Link> to <Link id="link">Home</Link>.
Alternatively, you can add the legacyBehavior prop <Link legacyBehavior><a id="link">Home<a></Link>.
<button> and <a> do not allow interactive content to be their content.
That said, you're passing invalid children to your <Link> component and to the <button> element:
<Link href={linkName} passHref>
<div className="col-lg-4 p-3 text-center text-lg-start border-0">
<h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
<p className="lead">{title1}<br /> {title2}</p>
<p className="lead">{desc1}</p>
{/* Invalid child */}
<button className="btn link btn-primary btn-xl w-100">
{/* Invalid child */}
<Link href={linkName} passHref>
<a> {buttonText}</a>
</Link>
</button>
</div>
</Link>
That may be the reason of why your component is behaving oddly.
PS. Formatting your code helps by making it more readable. :). You can do that by setting ESLint and Prettier up.
You maybe need to add the legacyBehavior as props in the next/link component.
import Link from 'next/link'
function Legacy() {
return (
<Link href="/about" legacyBehavior>
<a>About Us</a>
</Link>
)
}
export default Legacy
docs: https://nextjs.org/docs/api-reference/next/link#if-the-child-is-a-tag

React not rendering component with inline styling on IOS

I ran into a problem with my component not re-rendering after a state change, when using props driven inline styling, on IOS/iphone (not tested on ipad).
Here is the code sandbox: https://codesandbox.io/s/confident-meitner-2sju9?file=/src/FlexboxGap.jsx
Edit: adding the code here too as requested:
import { useState } from "react";
import "./FlexboxGap.styles.css";
function FlexboxGap({ visible, containerCat, propertiesCat }) {
const [gap, setGap] = useState(0);
const [rowGap, setRowGap] = useState(0);
const [columnGap, setColumnGap] = useState(0);
function onGapChange(event) {
setGap(event.target.value);
setRowGap(event.target.value);
setColumnGap(event.target.value);
}
function onRowChange(event) {
setRowGap(event.target.value);
}
function onColumnChange(event) {
setColumnGap(event.target.value);
}
return (
<div className="main-container">
<div>
{" "}
<div>gap: {gap}px</div>
<input
type="range"
className="slider-bar"
min={0}
max={20}
value={gap}
onChange={onGapChange}
/>
</div>
<div>
{" "}
<div>row-gap: {rowGap}px</div>
<input
type="range"
className="slider-bar"
min={0}
max={20}
value={rowGap}
onChange={onRowChange}
/>
</div>
<div>
{" "}
<div>column-gap: {columnGap}px</div>
<input
type="range"
className="slider-bar"
min={0}
max={20}
value={columnGap}
onChange={onColumnChange}
/>
</div>
<div
style={{
width: "100vw",
height: "250px",
backgroundColor: "grey",
display: "flex",
flexFlow: "row wrap",
justifyContent: "flex-start",
alignContent: "flex-start",
rowGap: `${rowGap}px`,
columnGap: `${columnGap}px`
}}
>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
<div className="graph-item">item</div>
{/* This last invisible div is a hack to "force" react to re-render, by referencing the props rowGap and columnGap.
Otherwise, the rerender fails to happen on iphones. Working on Android
and desktop */}
<div className="hack-ghost">{`${rowGap}${columnGap}`}</div>
</div>
</div>
);
}
export default FlexboxGap;
While the state of rowGap and rowColumn is successfully changed, as well as the style, the div that depends on it does not get updated on iphones (fully updated).
Works on desktop and android devices.
I found a hack by adding a div that references the 2 states I need, and everything now "works".
The problem is:
1- it is hacky and
2-i am not sure i fully understand what is going on.
I thought of this hack by thinking that "i needed react to notice that the state changed inside this element".
Is it an issue with the way that inline css works // an ios implementation particularity?
Kind regards.

Trying to render a full page video background in Next.js but getting blank page

I'm trying to have a full page video background in the homepage of my Nextjs application but am just getting blank white space where the content should be.
I'm fairly new to Nextjs and am probably making a silly mistake here, if anyone could point this out I'd really appreciate the help.
My mp4 video is stored within public/assets as so here:
This is my index.js file:
import Head from 'next/head';
import Image from 'next/image';
import React, { useRef, useEffect, useState } from 'react';
import ScrollAnimation from '../components/ScrollAnimation';
import Footer from '../components/Footer';
import Header from '../components/Header';
export default function Home() {
return (
<div>
<Head>
<title>Greystone</title>
<link rel='icon' href='/favicon.ico' />
<link
rel='preload'
href='/fonts/FairplayDisplay/FairplayDisplay-Bold.ttf'
as='font'
crossOrigin=''
/>
<link
rel='preload'
href='/fonts/FairplayDisplay/FairplayDisplay-Regular.ttf'
as='font'
crossOrigin=''
/>
</Head>
<main className='overflow-y-hidden h-screen'>
<Header />
<div
id='main'
className='transition duration-1000 relative ease-in-out'
onWheel={scrollTo}>
{/* Page 1 */}
<div className='h-screen w-full flex items-center'>
<video autoplay loop muted className='w-full h-screen z-10'>
<source
src='../public/assets/bubble-video.mp4'
type='video/mp4'
/>
</video>
<div className='flex flex-col absolute right-20'>
<ScrollAnimation />
</div>
<div className='w-2/5 text-left flex flex-col text-white left-20 absolute'>
<h2 className='text-5xl'>We’re Greystone.</h2>
<h2 className='text-5xl'>
We think recruitment is broken. Be part of something better.
</h2>
<p className='text-left mt-5 text-lg'>
Greystone brings the top 10% of talent together in an exclusive
club, then pairs those dream hires with the right clients. It’s
role-finding, reimagined.
</p>
<div className='mt-5 border-b-2 border-white w-36'>
<h3 className='text-left text-lg'>FIND OUT MORE</h3>
</div>
</div>
</div>
</div>
<Footer />
</main>
</div>
);
}
Many thanks in advance if anyone can help!
It seems I didn't need to have 'public' in the src url call for anyone who may experience a similar issue in future. The video tag now looks like so:
<video autoPlay loop muted className='w-full h-screen z-10'>
<source src='/assets/bubble-video.mp4' type='video/mp4' />
</video>
adding mute attribute to the video tag solved a similar issue for me
<video
preload="auto"
playsInline
autoPlay
muted
loop
>
<source src="/video.mp4" type="video/mp4" />
</video>

Why is video player working here and not there

I made a Sandbox showing the problem. In the Sandbox the Video player is working but replacing the code with below code is not working. If I move the src={filePa.. to <video.. then it works but without caption dunno
I write this code and it works:
return (
<div className="pg-driver-view">
<div className="video-container">
{this.renderLoading()}
<video
style={{ visibility }}
controls
type={`video/${fileType}`}
onCanPlay={e => this.onCanPlay(e)}
src={filePath}
>
Video playback is not supported by your browser.
</video>
</div>
</div>
);
Then I try this and it's not working the player does not show no warning no messages in the log:
return (
<div className="pg-driver-view">
<div className="video-container">
{this.renderLoading()}
<video style={{ visibility }} controls onCanPlay={e => this.onCanPlay(e)}>
Video playback is not supported by your browser.
<source src={filePath} type={`video/${fileType}`} />
<track src="test_captions_en.vtt" kind="captions" srcLang="en" label="hello_english_captions" />
</video>
</div>
</div>
);
Any idea?

Resources