Closing webcam without reloading - reactjs

I'm a a beginner in web development and I’m working on a video chat app built with create-react-app. I’m using recordRTC library for record and stream from users’s webcam and microphone.
When I stop recording, I also would like to close the webcam.
import React, { Component } from "react";
import RecordRTC from "recordrtc";
const captureUserMedia = callback => {
const params = { audio: true, video: true };
navigator.mediaDevices
.getUserMedia(params)
.then(callback)
.catch((error) => {
console.error(JSON.stringify(error));
});
};
export default class Recorder extends Component {
constructor(props) {
super(props);
this.recordVideo = null;
this.videoRef = React.createRef();
}
componentDidMount = () => {
captureUserMedia(stream => (this.videoRef.current.srcObject = stream));
};
startRecord = () => {
captureUserMedia(stream => {
this.recordVideo = RecordRTC(stream, { type: "video" });
this.recordVideo.startRecording();
});
};
stopRecord = () => {
this.recordVideo.stopRecording();
this.videoRef.current.srcObject.getTracks().forEach((track) => {
track.stop();
});
};
render() {
return (
<div>
<video ref={this.videoRef} autoPlay muted />
<div>
<button onClick={this.startRecord}>START</button>
<button onClick={this.stopRecord}>STOP</button>
</div>
</div>
);
}
}
I found here a related post where I found this:
stream.getTracks().forEach((track) => {
track.stop()
})
This stop the stream but the red circle is still present on the navigator tab (chrome) and the webcam's light is still lightning.
How can I do to turn off the webcam ?
The only way i found is to force a reload but I don't really wanna do this ...
If someone have an idea, please let me know.
Thanks for your reply :)

I found what I did wrong !
I called two times getUserMedia() method instead of one only (with captureUserMedia function).
You can try with the code below it will be ok !!!
...
componentDidMount = () => {
captureUserMedia((stream) => {
this.videoRef.current.srcObject = stream;
this.recordVideo = RecordRTC(stream, { type: "video" });
});
};
startRecord = () => {
this.recordVideo.startRecording();
};
stopRecord = () => {
this.recordVideo.stopRecording();
this.videoRef.current.srcObject.getTracks().forEach((track) => {
track.stop();
});
};
...

Related

How to write these plugin initialized in functional component?

I got an example like this
Before ever thing I need to import the payment from the plugin
import Payment from 'react-gg-payment';
This is the code from the website. example is given in classco
class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
isLoading : false,
payment_status : 'initiated'
};
var appServiceConfigData = {
"environment" : "test",
"base_url": "https://checkoutshopper-test.com/checkoutshopper/demoserver/",
"additional_http_headers" : {
"x-demo-server-api-key": DEMO_SERVER_API_KEY
}
};
Payment.initialize(appServiceConfigData);
Payment.onSuccess((payload) => {
this.setState({payment_status: 'success'});
console.log(payload);
});
Payment.onError((code, error) => {
console.log("Error : ",error);
this.setState({payment_status: 'failure'});
});
}
This is the example given by the library.
What I want is I wanna convert these codes into function component.
I don't know whether my code is true or false. This is my progress so far
const FuncApp = ({navigation}) => {
const [loading, setLoading] = useState(false);
const [paymentStatus, setPaymentStatus] = useState('initiated');
useEffect(() => {
var appServiceConfigData = {
"environment" : "test",
"base_url": "https://checkoutshopper-test.com/checkoutshopper/demoserver/",
"additional_http_headers" : {
"x-demo-server-api-key": DEMO_SERVER_API_KEY
}
};
Payment.initialize(appServiceConfigData);
},[])
//IDK WHERE TO PUT BELOW CODES
Payment.onSuccess((payload) => {
setPaymentStatus('success');
console.log(payload);
});
Payment.onError((code, error) => {
console.log("Error : ",error);
setPaymentStatus('failure');
});
in the return statement.
I got a button with onPress
const onClickPayment = () => {
Payment.startPayment()
}
<Button
label={'Pay'}
title="Pay"
color="#841584"
onPress={() => {
onClickPayment();
}}
/>

webcam not opening in webrtc with react.js

import React from 'react';
class Test extends React.Component {
constructor(props){
super(props);
this.status = {
}
}
componentDidMount(){
const pc = new RTCPeerConnection();
document.getElementById("call").onclick = async () => {
const stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
document.getElementById("video").srcObject = stream;
for (const track of stream.getTracks()) {
pc.addTrack(track, stream);
}
};
pc.ontrack = ({streams}) => document.getElementById("video").srcObject = streams[0];
pc.oniceconnectionstatechange = () => console.log(pc.iceConnectionState);
pc.onicecandidate = ({candidate}) => sc.send({candidate});
pc.onnegotiationneeded = async () => {
await pc.setLocalDescription(await pc.createOffer());
sc.send({sdp: pc.localDescription});
}
const sc = new window.localSocket(); // localStorage signaling hack
sc.onmessage = async ({data: {sdp, candidate}}) => {
if (sdp) {
await pc.setRemoteDescription(sdp);
if (sdp.type == "offer") {
await pc.setLocalDescription(await pc.createAnswer());
sc.send({sdp: pc.localDescription});
}
} else if (candidate) await pc.addIceCandidate(candidate);
}
}
render(){
return (
<div>
<video id="video" height="120" width="160" autoplay>
</video>
<br/>
<button id="call">Call!</button>
<br/>
<div id="div"></div>
</div>
)
}
}
export default Test;
Here is my code to open webcam.
I am following https://jsfiddle.net/jib1/2yLakm60 link an doing in react.js
https://jsfiddle.net/jib1/2yLakm60
But, my code is not working.
Webcam light is coming but camera is not showing.
Please take a look hOw can i solve this.

React shows a stale state in the render

I have an Image class which allows me to change images from the containiner Component and update the image style.
My Class:
import React from "react";
import Radium from 'radium';
class StateImage extends React.Component {
constructor(props) {
super(props);
this.state = {
images: this.props.images.map(image => ({
...image,
loaded: false,
activeStyle: {visibility: 'hidden'}
})),
activeMode: props.activeMode
};
this.state.images.forEach((image, index) => {
const src = image.image;
const primaryImage = new Image();
primaryImage.onload = () => {
const images = [...this.state.images];
images[index].loaded = true;
if (images[index].name === this.state.activeMode) {
images[index].activeStyle = images[index].style;
// is this image the default activated one? if so, activate it now that it's loaded.
images[index].onActivate();
} else
images[index].activeStyle = {visibility: 'hidden'};
this.setState( {
...this.state,
images
});
};
primaryImage.src = src;
});
}
updateImageStyle = (name, style) => {
let images = [...this.state.images].map( (image) => {
if (image.name === name) {
return {
...image,
style: style,
activeStyle: style
}
} else return image;
});
this.setState({
...this.state,
images: images
}, () => {
console.log("updated state");
console.log(this.state);
});
};
onClick = () => {
this.state.images.map( (image) => {
if (image.clickable && image.name === this.state.activeMode)
this.props.eventHandler(this.state.activeMode);
});
};
render () {
console.log("render");
console.log(this.state.images);
let images = this.state.images.map((image, index) => {
return <img
key={ index }
onClick={ this.onClick }
style={ image.activeStyle }
src={ image.image }
alt={ image.alt}/>
});
return (
<div>
{images}
</div>
);
}
}
export default Radium(StateImage);
My problem revolves around updateImageStyle. When this function is called I need to change the style element of the active image and re-render so that users see the change.
updateImageStyle is reached, and I update the images portion of my state. I console.log it once the setState is done and I can verify the change was made correctly!
However, I also console.log from the render and to my amazement, the this.state.images outputted from render is stale and does not reflect my changes.
How can this be? the console.log proves the render that has the stale state is called AFTER I have confirmed my changes have taken place.
My console log:
You are most likely seeing your state being overwritten by a different setState call perhaps the one in primaryImage.onload. Since React batches setState calls together, render() is called only once with the updates.

Vega graphs only render on hover when using React

I'm attempting to embed a Vega-Lite graph into a React.js application as follows:
class ClusterDistribution extends Component {
createPlot = () => {
...
vegaEmbed(this.node, spec, { actions: false }).then(res => {
res.view.insert("myData", myData);
});
};
componentDidUpdate() {
this.createPlot();
}
render() {
return <div ref={node => (this.node = node)} />;
}
}
The data loads well, but there is an odd behavior where it will only draw the bars when I hover as seen in this video:
show on hover
Any thoughts on why this may be happening would be great!

React native splash screen and navigate to different screen

I am beginner in using React Native.
I want to display the splash screen for my apps (for 1 second) and the navigate to different screen.
I have followed and combined some tutorial but I got an error.
My code is like this:
class SplashScreen extends React.Component {
static navigationOptions = {header: null,}
constructor(props){
super(props);
this.state = {
timePassed: false
};
}
render() {
let that = this;
setTimeout(function(){that.setState({timePassed: true})}, 1000);
const { navigate } = this.props.navigation;
if (!this.state.timePassed){
return (
<View style={styles.splashContainer}>
<Image source={require('./image/splash_screen.png')} style=
{styles.splash} />
</View>
);
}
else{
() => navigate('Login');
}
}
I got an error to navigate to new screen.
Can anyone help me? or is there any better solution?
Thank you.
Try this
class SplashScene extends Component {
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
await timeout(3000);
return fn(...args);
}
resetAndNavigate() {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Login'})
]
})
this.props.navigation.dispatch(resetAction)
}
componentDidMount() {
sleep.then(
this.resetAndNavigate()
)
}
}

Resources