'Why `muted` attribute on video tag is ignored in React?
Well, as counter-intuitive as it sounds, muted tag is somehow ignored; check out the snippet below,
first one is rendered with react, the second one regular html; inspect them with your dev tools, and you see the react on doesn't have muted attribute; I already tried muted={true}, muted="true" but non is working.
function VideoPreview() {
return (
<div className="videopreview-container">
React tag:
<video
className="videopreview-container_video"
width="320"
height="240"
controls
autoPlay
muted
>
<source src="https://raw.githubusercontent.com/rpsthecoder/h/gh-pages/OSRO-animation.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
);
}
ReactDOM.render(<VideoPreview />, root)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<hr/>
Regular html:
<video
width="320"
height="240"
controls
autoplay
muted
>
<source src="https://raw.githubusercontent.com/rpsthecoder/h/gh-pages/OSRO-animation.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
Solution 1:[1]
As mentioned by @FluidSense it is an open bug since forever.
I could achieve it like this:
import React, { useRef, useEffect } from "react";
export default function Video({ src, isMuted }) {
const refVideo = useRef(null);
useEffect(() => {
if (!refVideo.current) {
return;
}
if (isMuted) {
//open bug since 2017 that you cannot set muted in video element https://github.com/facebook/react/issues/10389
refVideo.current.defaultMuted = true;
refVideo.current.muted = true;
}
refVideo.current.srcObject = src;
}, [src]);
return (
<video
ref={refVideo}
autoPlay
playsInline //FIX iOS black screen
/>
);
}
Solution 2:[2]
Here is how I dealt with it using dangerouslySetInnerHTML:
import React, { Component } from "react";
export default class VideoComponent extends Component {
state = {
videoStr: "",
};
componentDidMount() {
const { src } = this.props;
const videoStr = `
<video autoplay loop muted>
<source src=${src} type="video/mp4" />
</video>
`;
this.setState({ videoStr });
}
render() {
return (
<div
className={this.props.className}
dangerouslySetInnerHTML={{ __html: this.state.videoStr }}
/>
);
}
}
Solution 3:[3]
I would also note that some browsers like Chrome might have a limit for the file size a video can be. I was running my own videos on my website and when I inspected the page and looked under Sources I did not find the video I had used and been looking for. This forced me to investigate further. I realized the video that I was running was about 10.4mb. It was large relative to the usual payload of a website so I lowered the size to around 5mb and the video appeared on my site.
Some other information about my steps to finding a solutions was that I was using my localhost to run my React app. I also ran my React app on Safari which surprisingly displayed my video even when the size was 10.4mb. I'm guessing that browsers have different criteria for video sizes.
Solution 4:[4]
muted works if you type it as muted="true". Using the string true sends the attribute to the DOM now
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CodingYourLife |
| Solution 2 | Mhmdrz_A |
| Solution 3 | Cap Lee |
| Solution 4 | itwasmattgregg |
