React: Using State Variable In Image Src? - reactjs

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

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'/>
}
</>
)

Add image to the DOM dynamically in react

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 )

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]}/>;

React - pass props/state to rendered HTML string?

In my React app, I have stored a text template as an HTML string on the server which is passed up to the client to be rendered. Is it possible to render this HTML string in such a way that it can access it's parent component state/props? I've tried using dangerouslySetInnerHTML and ReactDOMServer.renderToString(), both of which render the string as HTML, but render {props.text} as a literal string, rather than a reference to the component's props.
For example, on the server I have stored:
<div>Welcome to my app</div>
<div>{props.message}</div>
<div>Have fun</div>
And the component
import React from "react"
import { connect } from "react-redux"
const mapStateToProps = (state) => {
return { state }
},
WelomeBody = (props) => {
return (
<div dangerouslySetInnerHTML={{"__html": props.state.welcomeMessageBody}} />
)
}
export default connect(mapStateToProps, null)(WelomeBody)
but this results in:
Welcome to my app
{props.message}
Have fun
Is there a way that this can be rendered so as to access the value of props.message, rather than just rendering it literally?
If what you have in mind is to send down a React component (in JSX syntax) from your server to your client and have the client somehow rehydrate/compile it into an actual, working component, this is not achievable that easily.
When you build and bundle your React app, only components that are statically referenced/imported in your application at compile time can be used at runtime on the browser.
So, in order to dynamically render a component from a template and embed variables into it, your choices are:
Render it into final HTML on your server, send down that HTML and have a simple React component perform dangerouslySetInnerHTML for it. But, like you've already observed, that content has to be the full HTML code, no templates, variables, JSX, etc. Everything is string and HTML at this point, no more processing.
Alternatively, send down a Markdown document and have a Markdown component parse it into HTML and display it.
Create a sophisticated component that can receive a string, parse it, tokenize it, substitute values in it, etc. Essentially, create your own template-processing component that can read a template (the string sent down from your server) and embed the appropriate values into it.
A simple solution (to substitute values into a template) would be:
function Filler(props) {
let html = props.template;
Object.keys(props).forEach(key => {
if (key !== "template")
html = html.replace("{" + key + "}", props[key]);
});
return <div dangerouslySetInnerHTML={{__html: html}} />;
}
and use it like
<Filler template={"<h1>Hello, {firstname} {lastname}</h1>"} firstname="John" lastname="Doe" />
But again, this is far from a full-fledged actual React component.

Dynamic loading of locally stored images with react native

Problem with dynamic loading of image resources within a loop/list.
I have all my static local resources required as such:
assets/images.js
const images = {
appLogo: require('./app-logo.png'),
cardOne: require('./cards/card-1.png'),
cardTwo: require('./cards/card-2.png'),
...
cardForty: require(./cards/card-40.png)
}
export default images;
Then in my list screen:
...
import images from '../assets/images';
...
renderListItems(item) {
const image_name = `images.card${item.cardName}`;
console.log(image_name); // images.cardOne, images.cardTwo etc..
return (
<ListItem avatar>
<Thumbnail square size={80} source={image_name} /> // This is nativebase component which wraps the RN image component
<Body>
<Text>{item.name}</Text>
</Body>
<Right>
<NBIcon name="arrow-forward" />
</Right>
</ListItem>
);
}
...
No resources get loaded. Yet if I change the source={image_name} to source={images.cardOne} directly (where images.cardOne is the exact same as image_name variable on the first iteration) it works - except for the fact that they all have the same image.
I also tried using {{ uri: image_name }} syntax but nothing happens there too.
There doesn't seem to be any solution to this, other than creating a massive switch statement
Well that's because image_name is a string with the value of images.cardOne whereas images.cardOne is also a string but with the value of the actual path of the images in your file system (e.g ./app-logo.png). So if you want to load images object dynamically to image_name, you should use the bracket notation like so:
const image_name = images[`card${item.cardName}`];
That way image_name will now point to the path of your images (e.g ./app-logo.png).

Resources