Changing the URL of a background image in React - javascript

I'm trying to change background image by accessing DOM and changing css property like so:
///anotherweathermap.js
const changePic = () => {
document.getElementById('bckgAnother').style.backgroundImage = "url(../img/kaunas.jpg)";
}
The image will not load
but when I put the img path in css, the img path is different:
If I insert the same path, the one with static/media.., the DOM manipulation works.
This is the order of files:

Relative URLs in CSS images are computed between the location of the style sheet (which will be the URL of the webpage itself for inline CSS) and the URL of the image.
They have nothing to do with either:
The URL of the JS file
The location on the file system of the JS file
The location on the file system of the image (except in so far as that is used to determine the URL it gets)
Since you are using React, you will need to import the image and then use the imported value of it to get the URL.
You should change your logic to set the value based on state and avoid direct DOM manipulation.
import Default from '../img/default.jpg';
import Kaunas from '../img/kaunas.jpg';
const AnotherWeatherMap = (props) => {
const [background, setBackground] = useState(Default);
const css = {
backgroundImage: `url(${background})`
};
return (<div style={css}>
<button onClick={ () => setBackground(Kaunas) }>Change background<button>
</div>);
};

Related

How to require and display images dynamically in React?

I'm facing an issue when I try to display images inside my React App component
I have all the images I need, divided by set, in this path src/cards_images/ inside root folder.
In this way I can reach for cards in different sets like:
src/cards_images/set1_MyFirstSetName_MyCard1.jpg
src/cards_images/set2_MySecondSetName_MyCard1234.jpg
I need to create images dynamically, because on this component I pass an array of objects, with the right source path. If I hard-code the same source path, it works, but if I dynamically try to create the path, React says it can't find the module.
I can't put every image inside Public folder because we are talking about several thousands of 200kb images and it won't load. Neither I can import/require every image in bulk, because it will not work aswell (still, how to filter/show them?). It has to be dynamically required and showed. How can I do it? Am I doing anything wrong on this?
import React , {Component}from 'react';
function CardDisplay({ sets }) {
return (
<div id="myDeckCardPickerContainer">
{sets?.map(settino => {
// Gives error "Module not found"
var temp = require(settino.url)
return <div key={settino.key} className='cardImageContainer'><img className='cardImagePreview' src={temp} alt={settino.Name}></img><div><span className='addCardToDeck'>➕</span>{settino.name}<span className='removeCardFromDeck'>➖</span></div></div>
// Gives error "Module not found"
return <div key={settino.key} className='cardImageContainer'><img className='cardImagePreview' src={require(settino.url)} alt={settino.Name}></img><div><span className='addCardToDeck'>➕</span>{settino.name}<span className='removeCardFromDeck'>➖</span></div></div>
// Works fine
return <div key={settino.key} className='cardImageContainer'><img className='cardImagePreview' src={require('../cards_images/set1_MyFirstSetName_MyCard1.jpg')} alt={settino.Name}></img><div><span className='addCardToDeck'>➕</span>{settino.name}<span className='removeCardFromDeck'>➖</span></div></div>
})}
</div>
)}
export default CardDisplay;

ReactJS Functional Component Renders Multiple Times and Setting Img Src With Props

I am a newbie in ReactJS and I am trying to pass an object as a props to a component. I am getting data from the .NET CORE WEB API and there is no problem about it. Here is my useEffect hook to do that:
useEffect(() => {
const response = axios.get("http://localhost:5122/GetUserInfo", { params: { userId: profileId } });
response.then((res) => {
setUserInfo(res.data);
})
}, [])
And I pass the userInfo state as props, as shown below:
return (
<div>
<ProfileCard user={userInfo} />
</div>
);
To better understand of problem I took a screenshot of console. I am print user prop at the top of ProfileCard component.
Console Screenshot
My problem is:
When I try to use props such as <label>{user.profilePicture}</label> I can see the file name on the screen but when I try to use props such as <img src={require(./File/${user.profilePicture})} /> cannot see the image on the screen and throws an error to console that basically saying cannot find the image. Note:I am sure that given source path is correct and image file exist.
Anybody help me please? Edit: I also added the console error.
Your screenshot shows that profilePicture is a filename à la 36ddd13a-d3b9-47ad-9719-7789892a1384.jpg.
Just doing <img src={profilePicture} /> would have your browser attempt to find the file by relative path, which is likely not to work.
require(...) only works for assets that are available at the build time of your React app and only for static strings due to bundling; an arbitrary filename that comes over the wire from your API won't be that.
If your HTTP server serves those images from under /File, then you'd need to do
<img src={`/File/${profilePicture}`} />
(or, if that HTTP server is not the same origin your React app is served from, but that http://localhost:5122/ from above),
<img src={`http://localhost:5122/File/${profilePicture}`} />
).
If you're using e.g. create-react-app, then you'd need to put the file in the /public/File/ directory.
You can't pass dynamic strings to require like require(./File/${user.profilePicture})
It maybe work sometimes, but only in some edge cases.
What you should do is tell the compiler exactly which files it needs to bundle:
const map = {
'profilePic_1': require('./File/profilePic_1'),
'profilePic_2': require('./File/profilePic_2'),
// and so on...
}
By creating a map you can then "index" the bundled files based on server response.
<img src={map[user.profilePicture]} />
If you have a fairly large number of images I'd recommend dynamically loading them:
const map = {
'profilePic_1': () => import('./File/profilePic_1'),
'profilePic_2': () => import('./File/profilePic_2'),
// and so on...
}
const YourComponent = ({userProfilePicture})
{
// without placeholder
const [url, setUrl] = useState('');
// if you want to load a placeholder from a server
// const [url, setUrl] = useState('http://placeholder_url');
// if you want to bundle the placeholder
// const [url, setUrl] = useState(require('./placeholder_url'));
useEffect(() => {
map[userProfilePicture]().then(setUrl);
}, []);
return <img src={url} alt=''/>;
}
Please can you post the entire component with the useEffect and also the ProfileCard component.
It might be a problem with the useState.
You should have something like
const [userInfo, setUserInfo] = useState<TypeOfGetUserInfo | null>(null)
In you ProfileCard you should have something like
const ProfileCard = React.FC<ProfileCardProps> = ({user}) => {
...
return (
...something
)
}

VueJS - Update parent values from emit with parameters?

I don't really know how to put it but i'll explain:
I have a form where the user can upload an image. The upload image goes as followes
<input id="visualisation_upload" #change="onThumbnailChanged" name="visualisation_upload" accept="image/*" type="file" class="sr-only">
onThumbnailChanged (event) {
const file = event.target.files[0];
this.fields.thumbnail = file;
this.fields.thumbnailPreview = URL.createObjectURL(file);
},
I want to show the user which files has been uploaded and let them delete the files if they so desire. For that exact purpose I use a component called uploadedFiles
I call the component like follows:
<uploadedFiles v-if="this.fields.thumbnail" :file="this.fields.thumbnail" :preview="this.fields.thumbnailPreview" #update-images="updateFiles"></uploadedFiles>
Within the uploadedFiles component I have a click Event that is supposed to empty both props within uploadedFiles AND the props that were passed to the component. When I try do to it directly within the component like this (Which you shouldn't do) I of-course get Avoid Mutating a Prop Directly:
deleteFiles() {
this.file = ''
this.preview = null
}
Within the parent component I have a method there I would like to empty the values like this
<a #click="$emit('update-images', file, preview), file = '', preview = null" class="hover:text-gray-900 cursor-pointer"></a>
updateFiles: function(file, preview) {
file = ''
preview = null
},
But I can't seem to make it work. I am trying to make the component dynamic so I don't have to create the method in each component.
I don't know if i am making any sense. Point is, when clicked on the button. Empty both this.fields.thumbnail & file from the component. How can I accomplish this?
You can emit update:xxx events and then use xxx.sync modifier in the parent (https://v2.vuejs.org/v2/guide/components-custom-events.html#sync-Modifier):
<uploadedFiles
v-if="this.fields.thumbnail"
:file.sync="this.fields.thumbnail"
:preview.sync="this.fields.thumbnailPreview"
/>
deleteFiles()
{
this.$emit('update:file', '');
this.$emit('update:preview', null);
}

Proper way to load local stored images from folder in React

I am calling the OpenWeatherMap API and getting in the response the iconID like 01d or 04n. I've set up all the images under a local directory in /src and named them 01d.png, 04n.png etc.
I've passed this iconID via props to my Current.js component and I don't know how can I display the image with the specific id name.
E.G:
I would like to display image 01d.png if the response from the server is equal to 01d
P.S:
props.icon stores the data from the server and it is indeed good data.
import React from 'react';
import classes from './Current.module.css';
const current = (props) => {
return (
<div className={classes.Current}>
<p>Temperature: {props.temperature}</p>
<p>Minimum Temperature: {props.minimumTemperature}</p>
<p>Maximum Temperature: {props.maximumTemperature}</p>
<p>Humidity: {props.humidity}</p>
<img src={'../../icons/' + props.icon + '.png'}[enter image description here][1] alt={props.icon}/>
</div>
)
}
export default current;
Here is a screenshot of my folder structure
First of all make sure that the images folder is not out of src, then load image like
<img src={require(`../../icons/${props.icon}.png`)} />
Or if it is only one image id passed to component and no need for maping you can lazy load it when component renders.
const current = (props) => {
const pic = React.lazy(()=>import(`../../icons/${props.icon}.png`))
......
Then wrap the img tag with Suspense and <img src={pic} />

require() not working with interpolated string when fetching an image in react native

I am using an Image component as a background in React Native and am currently providing the source prop with an image as follows, which works.
const ImageWrapper = (props) => {
return (
<Image source={require('../../../images/testingImages/cells.png')} style={styles.imageView}>
{props.children}
</Image>
);
};
However, I would like to provide the require with an interpolated string with the name of an image provided by a prop as so:
require(`../../../images/testingImages/${props.imgURL}`)
But whenever I do so (even when I create the string as a seperate variable without using ES6 and pass it into require). I get the error -
"unknown named module '../../../images/testingImages/cells.png'".
Is there away to get the image without using require? As I would love to be able to pass the image url as a prop so that I can reuse the component when I want to change the background.
Any help is much appreciated!
Hopefully somebody else can provide a solution to your exact problem because I was having the same issue, but my workaround was to pass the entire value for source as a prop. I had that as a value to a certain key for each map within a list in my scenario, so that was clean enough for me. But that may be just moving the problem up a level in your case.
First create a file with image required - React native images must be loaded this way.
assets/index.js
export const leftChevron = require('./left-chevron.png');
export const rightChevron = require('./right-chevron.png');
export const circle = require('./oval-bottom-right.png');
export const homeandgarden = require('./homeAndGarden.png');
Now import all your assets
App.js
import * as All from '../../assets';
You can now use your image as an interpolated value where imageValue is the same as named local file:
<Image style={styles.image} source={All[`${imageValue}`]}></Image>
I am not sure if it solves your issue but if your image is available over network you can use your base URL to create a URL to the image and use that URL directly inside as a source.
var fileName = "trolltunga.jpg";
var imagesBaseUrl = "https://www.w3schools.com/css/";
var image = imagesBaseUrl+fileName;
const imageURL = {url:image}
class App extends React.Component {
render() {
return (
<Image source={imageURL} style={styles.imageView}>
</Image>
);
}
}
For demo check here https://rnplay.org/apps/hEYzcA
Here is how I got round it specifically, not really a perfect answer but works fro my purpose. I think the require is called when the component loads and hence the string doesn't get a chance to interpolate to be passed. So instead I import the relevant image in the parent component of image wrapper:
import jungle from '../../images/jungle.jpg';
Then pass as a prop to Image Wrapper
<ImageWrapper image={jungle} />
Then pass this prop to the image source component:
<Image source={this.props.image} style={styles.imageView}>
{ this.props.children }
</Image>

Categories