Add image to the DOM dynamically in react - reactjs

I have a socket connection that updates a binary data.
By click I would like to update an image src , the images are created blank with empty src and with id , but I did not found how do I doing something like :
$('imageId').src = 'new src' like in Jquery
I have array of images so I cant define per each image this.ref or something
my socket code: // here I want to update the specific image
divSocket.on('data', (data) => {
var bytes = new Uint8Array(data);
this.setState({
imageSrc : someBufferFunction(bytes)
})
});
my render code
{ this.props.list.map((item,i) =>(
<div className="img">
<img id={`cam${i}`} src={`data:image/jpeg;base64,${this.state.imageSrc}`} />
</div>
))}
the problem is that this.state.ImageSrc will update all images and will show socket data (video) in all the images
I can create an image with specific id in loop but how do I update specific image via props/state

You're using an array to display images ... from props ... this.props.list
This list should contain data for each image ... but item argument isn't used in .map rendering.
I need to make a placeholder
Assuming that props.list doesn't contain any data ... used as loop counter ... renders placeholders only ... you need:
an array of src in local state (this.state.sources = [];)
you should render images using key prop:
{ this.props.list.map((item,i) => (
<div className="img" key={`cam${i}`} >
<img id={`cam${i}`} src={this.state.sources[i]} />
</div>
))}
you can use placeholder image for empty 'cells'
<img id={`cam${i}`} src={this.state.sources[i] ? this.state.sources[i] : "url_somePlaceholder.jpg"} />
New image from socket needs to update an array element using index - not common one for all images in this.state.sources - see React: how to update state.item[1] in state using setState? for inspirations.
If assumed earlier props.list contains image sources at start - copy values into state (in componentDidMount, componentDidUpdate or static getDerivedStateFromProps )

Related

Can Dynamic and Constantly changing image URL work with Next/image

Can Next/Image use empty string variables for the src that'd get set later via an API?
I have an image url that I'd retrieve from an API. so the image src gets set after runtime. By default it's an empty string '' and then using SWR later it gets set to the full image url, eg https://i.imgur.com/Thgw1b.png
However, I get a build time error, Error: Image is missing required "src" property. Make sure you pass "src" in props to the `next/image` component. Received: {} despite having src already set. The same error occurs if src='' as well.
const myComponent = ({imageURL = ''}) => {
// imageURL starts off as '', then the parent updates that value to a proper image url when the API returns a url value.
return (
<>
// TODO: Fix build time error saying no src is set, despite being set to '' initially
<Image src={imageURL} alt='Dynamic Image' layout='responsive'/>
</>
);
}
Can Next/Image src images be set fully dynamically? Where it starts as an empty string then the src url gets populated later?
I've seen some answers suggesting useServerSide Props, but that won't work in my use case as the image url API gives a different image url every X hours (Hence using SWR). So just loading in once doesn't work.
Note that using <img> tags works perfectly. Initially there's no image, then after the image url gets set to the variable, the img tag loads the image in.
Try rendering the Image conditionally like so :
return (
<>
{imageUrl &&
<Image src={imageURL} alt='Dynamic Image' layout='responsive'/>
}
</>
)

How to place a box below one of the elements present on screen on click when the elements were present by 50 cards using .map() function

I have placed 50 elements on the screen using data.map()
When I click a element, it should open a Component below the clicked element. How should i do so?
your question could have been more clear. Use react state lift
basically you should have a state variable like selectedCard and store its key or something unique for each card.
So when you click on the card onClick={() => this.setState({ selectedCard: cardKey })
and in map function check while rendering if (cardKey === selectedCard) show the component in position: absolute and specify the absolute style properties so that it ll be displayed below your selected card.
Have a state variable that has a unique identifier (probably id or some key) of the clicked element. Then whenever an element is clicked update the state with clicked element's unique Id.
And conditionally render the box for matching element.
const [activeElement, setActiveElement] = useState(null);
.....
elements.map(element => (
<div key={element.uniqId} onClick={() => setActiveElement(element.uniqId)}>
// element jsx
{activeElement === element.uniqId && (
// box jsx
)}
</div>
))

React: Using State Variable In Image Src?

So I've exported all of the images in my image folder by using an index.js inside the same folder and writing exports such as export const Image = require("./image.png");. I then imported said images into my React app with import { Image, Image2, Image3 } from from "./imageFolder";
When I use the imported images as src values in my image tags, they work just fine so I know I've properly imported my image. The big issue that I have though is I've been trying to utilize the value of a state variable in the file to dynamically render a different image based on the state. The state variable's values are varied due to its values deriving from a database request that's stored in a state array.
{
Object.keys(this.state.videos).map((video, index) => {
return (
<div key={index}>
<p>Event: {this.state.videos[video].eventName}</p>
<p>P1 Character: {this.state.videos[video].p1Character}</p>
<p>P2 Character: {this.state.videos[video].p2Character}</p>
</div>
);
})
}
Say that in this instance, the value of {this.state.videos[video].p1Character} is equal to "Image" - which corresponds with the name of the image I imported above. So why can't I do <img src={this.state.videos[video].p1Character} />? Is it possible to do what I'm trying to do?
You cannot do it becaue the p1Character is a string and not a live variable.
You could however import the images as
import * as Images from from "./imageFolder";
and then use the p1Character to reference the image in the Images.
<img src={Images[this.state.videos[video].p1Character]} />
Unless I don't understand what you mean, I don't see how it would be possible to have this this.state.videos[video].p1Character equal to Image/Image2/Image3 if you have just save a reference to them as a string because you are literally just going to be writing src="Image/2/3".
The best thing to do would to be store a unique key string for the images on a record and then just have a simple object map in your component like
const myImageMap = {
image1: Image,
image2: Image2,
image3: Image3
}
/////
///// somewhere in your render
/////
<img src={myImageMap[this.state.videos[video].p1Character]} />
They key is that we are mapping to the strings to actual imported images

React add images to existing map

I have a react app where I fetch the item data from an API.
I'm mapping each item's data to a card in the react app.
this.props.item.map(item => {
return <Card data={item.name} key={item.id}/>;
This works, however I want to add a corresponding image to each item in the array and I'm not sure what approach to take to add images to an existing map.
The images are stored in the public folder and not available via the API. I want the correct image to correspond to the correct data.
Eg. data="flowers" key="123" src="../images/flowers.jpg"
Thanks!
Initially take the images from the public folder and add it to somewhere inside src say, src/assets/images.
Then you will have to create an object corresponding to each data value. Then map the value to the image name.
var flower = require("../assets/images/flowers.jpg");
var cat = require("../assets/images/cat.jpg");
var dog = require("../assets/images/dog.jpg");
var dictionary={"flowers":flower, "cat":cat,"dog":dog}
now when you get response from API,
you can use inside the card component as,
<img src={dictonary[props.name]}/>
You could add a new prop named src, and use it with the name of the item:
this.props.item.map(item => {
return <Card data={item.name} key={item.id} src={`${item.name}.jpg`}/>;
You can create an image to item.id map and there you can find image from your local.
example:
const imageIdMapper = {
1: require("./<path to image belongs to id one>),
2: require("./<path to image belongs to id two>),
...
}
then in your map
this.props.item.map(item => {
return <Card data={item.name} key={item.id} image={imageIdMapper[item.id]}/>;

creating a list with react-dropzone

I'm trying to create a gallery using react-dropzone. I am successfully adding images but instead of creating an array, as I thought I was doing by following their github, it is simply loading an image and replacing it with the new one when I drag another image. The expected result is to add the image next to the one I already dragged in it.
I am specifying an empty array called files: [], that I imagine will collect the images.
The dropzone element in my class looks like this:
let dropzoneRef;
<Dropzone
ref={
(node) => {
dropzoneRef = node;
}
}
onDrop={this.onDrop.bind(this)}>
<p>Drop files here.</p>
</Dropzone>
<RaisedButton
label="Upload File"
primary={false}
className="primary-button"
onClick={() => { dropzoneRef.open(); }}
/>
<ul>
{
this.state.files.map(f =>
<li key={f.preview}>
<img className="dropped-image" src={f.preview} alt=""/>
</li>,
)
}
</ul>
I added the working code to a WebpackBin for you to inspect
Their github docs are here
This is my goal screen. I haven't worked out the second part which is clicking on any single thumbnail added and showing it in full size. So don't worry about that part. I just need to be able to collect a list and add as many as I want. Here is a screenshot of the expected result. (I apologize for the kindergarten writing)
Thank you in advance
All you need to do is update your onDrop function as follows
onDrop(uploadedFile) {
this.setState({
files: this.state.files.concat(uploadedFile),
});
}
This is because you want to add the new file to this.state.files array.
See this updated WebpackBin.

Resources