Why preload image don't work? - reactjs

I wrote a component for preload images. Every image have got a lite version (prop previewUrl) and normal version (prop src)
It seems, everything should be ok, but it's not!. Event onload doesn't work. GET request doesn't happend. I break my mind and don't know where the misstake.
Here is a codepen https://codepen.io/fsdev/pen/bLWgoL of the code below
class Image extends React.Component {
constructor(props){
super(props);
this.state = { src: null };
this.preloadImage = this.preloadImage.bind(this);
}
componentWillMount(){
const { src: bigImage, previewUrl } = this.props;
this.setState({src: previewUrl});
this.preloadImage(bigImage)
.then(() => {
console.log("Loaded");
this.setState({src: bigImage});
})
.catch(e => console.error(e.message))
}
preloadImage(url){
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = url;
})
}
render(){
const { src } = this.state;
const { previewUrl, ...rest } = this.props;
return(
<img {...rest} src={src} />
)
}
}
class App extends React.Component {
render(){
return(
<Image src="http://res.cloudinary.com/playhs/image/upload/v1518304840/bsyjqxahzr8bmaxuvj04.png"
previewUrl="http://res.cloudinary.com/playhs/image/upload/q_30/v1518304850/ztpj7gnqazk6ng2tzamk.jpg"
/>
)
}
}
ReactDOM.render(
<App/>, document.body
)
Thank you

I'am stupid
My React Component called as Image
and here
const image = new Image();
I call here my own Component :) lol

Related

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.

Show a dummy text until image load in react

I have a React Component, and a JSON which consists of image url, i pass the image url into image tag in my component through mapping function.
Here is a Example of my Code:
import imgDetails from "../data/ImageDetails";
class Example extends Component {
constructor(props) {
super(props);
this.state = {
imgContentLoad: false
}
}
imageHandleLoad() {
this.setState({
imgContentLoad: true
})
}
render() {
return ({
imgDetails.map((imgDetails) => {
return ( <
React.Fragment > {
(this.state.imgContentLoad &&
<
img src = {
imgDetails.imgURL
}
onLoad = {
this.imageHandleLoad.bind(this)
}
/>) || <
div > image is loading < /div>
} <
/React.Fragment>
)
}
)
}
Here i want to display the "image is loading" text to show until the image loads so i wrote the above image onload function code. but my problem is, "image is loading" is showing infinitely the image is not showing. what is wrong here?
extract it to a new component that will listen to the onload event and return the img when its loaded
class ImageWithLoading extends React.Component {
state = { isLoaded: false }
componentDidMount() {
const image = new Image();
image.onload = () => this.setState({ isLoaded: true });
image.src = this.props.src;
}
render() {
const { src } = this.props;
const { isLoaded } = this.state;
return isLoaded
? <img src={src} />
: <div>Loading image...</div>
}
}
Then make the Example component just a container that maps the data to the ImageWithLoading component
const Example = () => imgDetails
.map(({ imgURL }) => <ImageWithLoading key={imgURL} src={imgURL} />);

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.

Updating video element src with different streams via blob URL

My react component 'VideoPlayer' doesn't update its src attribute as its props change.
Each time getUrlStreamForMostRecentMP4OnDb() is called a new blob Url object is created. This object streams the most recent video added to the database. No matter what the latest video on the database is the video element always renders the same initial video.
App.js
import React, { Component } from "react";
import VideoPlayer from "./VideoPlayer";
export default class App extends Component {
constructor(props, context) {
super(props, context);
this.getUrlStreamForMostRecentMP4OnDb = this.getUrlStreamForMostRecentMP4OnDb.bind(
this
);
this.state = {
playerSource: null,
};
}
async getUrlStreamForMostRecentMP4OnDb() {
fetch("http://localhost:4000/ytdl/streamMP4")
.then(re => re.blob())
.then(blob => URL.createObjectURL(blob))
.then(url => {
this.setState({ playerSource: url });
})
.catch(err => {
console.log(err);
});
}
render() {
return (
<div>
<button onClick={this.getUrlStreamForMostRecentMP4OnDb}>
Get url stream for most recent mp4 from db.
</button>
{this.state.playerSource ? (
<VideoPlayer
key={this.state.playerSource}
playerSource={this.state.playerSource}
/>
) : (
<div />
)}
</div>
);
}
}
VideoPlayer.js
import React, { Component } from "react";
export default class VideoPlayer extends Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<div>
<video
id="video"
width={300}
ref="player"
muted={true}
autoPlay={true}
loop
crossOrigin="anonymous"
src={this.props.playerSource}
>
</video>
</div>
);
}
}
I know this is an old question, but I got it to work by manipulating the dom directly like this:
const onUpload = ({ event, ContentId, ContentIndex }) => {
if (event.target.files.length) {
var UploadedVideo = event.target.files[0];
var MediaUrl = URL.createObjectURL(UploadedVideo);
var VideoElement = document.getElementById(`video_${ContentId}`);
if (VideoElement) {
VideoElement.src = MediaUrl;
VideoElement.load();
}
}
}

How do I manage my array of children components' states?

I'm new to react, so forgive me. I'm having a problem understanding states, specifically those of children.
Purpose: I'm trying to create a form that a user can append more and more components -- in this case, images.
What happens: User appends 2 or more images. User tries to upload an image with UploadButton component, but both the images are the same. I believe this has to do with both appended children sharing the same state.
Question: How do I give each appended child its own image without affecting the other appended children?
class Page extends Component
constructor (props) {
super(props);
this.state = {
id: '',
numChildren: 0,
images: [],
}
this.onAddChild = this.onAddChild.bind(this);
}
showModal() {
this.setState({
numChildren: 0,
images: [],
});
}
renderModal()
const children = [];
//Here's my array of child components
for(var i = 0; i < this.state.numChildren; i += 1) {
children.push(<this.ChildComponent key={i} />);
}
return (
<ReactModal>
<this.ParentComponent addChild={this.onAddChild}>
{children}
</this.ParentComponent>
</ReactModal>
)
}
onAddChild = () => {
this.setState({
numChildren: this.state.numChildren + 1
})
}
ParentComponent = (props) => (
<div>
{props.children}
<Button onClick={props.addChild}>Add Item</Button>
</div>
);
ChildComponent = () => (
<div>
<UploadButton
storage="menus"
value={this.state.images}
onUploadComplete={uri => this.setState({images: uri})}
/>
</div>
);
}
Here's the code for UploadButton:
import React, { Component } from 'react';
import uuid from 'uuid';
import firebase from '../config/firebase';
class UploadButton extends Component {
constructor(props) {
super(props);
this.state = {
isUploading: false
}
}
handleClick() {
const input = document.createElement("INPUT");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/gif, image/jpeg, image/png");
input.addEventListener("change", ({target: {files: [file]}}) => this.uploadFile(file));
input.click();
}
uploadFile(file) {
console.log('F', file);
const id = uuid.v4();
this.setState({ isUploading: true })
const metadata = {
contentType: file.type
};
firebase.storage()
.ref('friends')
.child(id)
.put(file, metadata)
.then(({ downloadURL }) => {
this.setState({ isUploading: false })
console.log('Uploaded', downloadURL);
this.props.onUploadComplete(downloadURL);
})
.catch(e => this.setState({ isUploading: false }));
}
render() {
const {
props: {
value,
style = {},
className = "image-upload-button",
},
state: {
isUploading
}
} = this;
return (
<div
onClick={() => this.handleClick()}
className={className}
style={{
...style,
backgroundImage: `url("${this.props.value}")`,
}}>
{isUploading ? "UPLOADING..." : !value ? 'No image' : ''}
</div>
);
}
}
export default UploadButton;
I tried to exclude all unnecessary code not pertaining to my problem, but please, let me know if I need to show more.
EDIT: This is my attempt, it doesn't work:
//altered my children array to include a new prop
renderModal() {
const children = [];
for (var i = 0; i < this.state.numChildren; i += 1) {
children.push(<this.ChildComponent imageSelect={this.onImageSelect} key={i} />);
}
//...
};
//my attempt to assign value and pass selected image back to images array
ChildComponent = () => (
<div>
<UploadButton
storage="menus"
value={uri => this.props.onImageSelect(uri)} //my greenness is really apparent here
onUploadComplete={uri => this.setState({images: uri})}
/>
//...
</div>
);
//added this function to the class
onImageSelect(uri) {
var el = this.state.images.concat(uri);
this.setState({
images: el
})
}
I know I'm not accessing the child prop correctly. This is the most complexity I've dealt with so far. Thanks for your time.
When you write this.state in Child / Parent component, you are actually accessing the state of Page. Now, I would recommend that you pass in the index of the child to the Child like so
children.push(<this.ChildComponent key={i} index={i}/>)
so that each children deals with only its own image like so
ChildComponent = ({index}) => (
<div>
<UploadButton
storage="menus"
value={this.state.images[index]}
onUploadComplete={uri => {
let images = this.state.images.slice()
images[index] = uri
this.setState({images})
}}
/>
</div>
);

Resources