I don't know, I've imported local images before but it isn't working today.
I have this helper file which exports the images as an array
const images = [
require("../assets/1.jpeg"),
require("../assets/2.jpeg"),
require("../assets/3.jpeg"),
require("../assets/4.jpeg"),
require("../assets/5.jpeg"),
require("../assets/6.jpeg"),
]
export default images;
Then I use them here to get a random image here
//Random Image
const randomImg = () => {
console.log(images);
const UU = images[Math.floor(Math.random * images.length)];
return UU;
}
const [hero, setHero] = useState(randomImg());
And then I get hat hero state in my jsx img tag
<img
className="headerImg"
src={hero}
alt="Hero Image"
/>
Why Isn't it working. I'm not using Next or gatsby or anything. I'm using React with webpack 2. Anyone know what is wrong?
Another interesting thing is that if I import a single image like this
import hero from "../../assets/1.jpeg";
And Use It directly in the image
<img
className="headerImg"
src={hero}
alt=""
/>
Suddenly, it works. What is the Problem?
Thanks,
Lakshya
Related
I've made this codesandbox example to illustrate my issue. I'd like to use a React component multiple times on one page that takes in an array of images and automatically cycles through them (using CSS via z-index or display).
I'd love to know the correct way of doing this, especially if it uses React Hooks instead of VanillaJS but any help would be much appreciated.
(Also, if this isn't the place to get specific help with code, can you point me in the right direct please)
Thanks!
Your issue is not with setInterval but with the way you're retrieving the slides list from you ImageSwapper component: document.getElementsByClassName("photo");
As all your images have a photo class, each ImageSwapper component will iterate through all the images, not just its children.
An easy solution given your approach is to assign a unique id to each ImageSwapper and use that id to group images by class (let's say the class will be photo_ + id}:
<ImageSwapper title="box 1" id="box_1">
<img src="..." className="photo_box_1"/>
<img src="..." className="photo_box_1"/>
<img src="..." className="photo_box_1"/>
</ImageSwapper>
<ImageSwapper title="box 2" id="box_2">
<img src="..." className="photo_box_2"/>
<img src="..." className="photo_box_2"/>
<img src="..." className="photo_box_2"/>
</ImageSwapper>
Then, in ImageSwapper you can retrieve the slides like this:
const ImageSwapper = ({ children, title, id }) => {
var slides = document.getElementsByClassName(`photo_${id}`);
...
}
Working stackblitz
I suggested you check out this useInterval hook implementation: https://usehooks-typescript.com/react-hook/use-interval
import { useEffect, useRef } from 'react'
function useInterval(callback: () => void, delay: number | null) {
const savedCallback = useRef(callback)
// Remember the latest callback if it changes.
useEffect(() => {
savedCallback.current = callback
}, [callback])
// Set up the interval.
useEffect(() => {
// Don't schedule if no delay is specified.
if (delay === null) {
return
}
const id = setInterval(() => savedCallback.current(), delay)
return () => clearInterval(id)
}, [delay])
}
export default useInterval
And if your interested have a read of the attached blog post by Dan Abromov:
https://overreacted.io/making-setinterval-declarative-with-react-hooks/
I'm currently rendering a child component when a signInError occurs. The signInError is stored in the parent component and if it's not null, it renders the <SignInError/> component, as per the code below:
ParentComponent.js
// Some code...
render() {
return(
<div>
<SignInForm
doSignIn={this.doSignIn}
resetSignInError={this.resetSignInError}
signInError={this.state.signInError}
/>
{this.state.signInError && <SignInError/>}
</div>
);
}
So far, so good, here's the child component SignInError.js
import React from 'react';
import RoundImage from '../../../UI/Common/RoundImage';
import Newman from '../../../../assets/newman-min.png';
class SignInError extends React.Component {
constructor(props){
super(props);
}
componentDidMount(){
const img = new Image();
img.src = Newman;
}
render(){
return(
<div>
<div>
<RoundImage src={img.src}/> // <--- img is undefined here!!!
</div>
<div>
Hello... Newman!
</div>
</div>
);
}
}
export default SignInError;
RoundImage.js
import React from 'react';
const RoundImage = (props) => {
return (
<div>
<img src={props.src}/>
</div>
);
}
export default RoundImage;
How to preload images in React.js?
This question's answer (link above) here on Stack Over flow tells me to create the img object inside the componentDidMount() method to force the browser to load it. And so I did, as you can see from the code above. But now, when I try to pass it as a prop to my grand-child component inside my render method, I can't access the img, because it was defined inside of another method.
What's the best way around this? I just need the image to be loaded and to be displayed together with the error message. Otherwise the error message will show before the image, if your browser hasn't cached it yet. Thanks for the help.
Image download happens in the browser. Rendering to the DOM also happens in the browser.
By preloading, do you mean that you want that the component renders only when the image is ready?
If so, you could do something like this:
componentDidMount() {
const img = new Image();
img.onload = () => {
// when it finishes loading, update the component state
this.setState({ imageIsReady: true });
}
img.src = Newman; // by setting an src, you trigger browser download
}
render() {
const { imageIsReady } = this.state;
if (!imageIsReady) {
return <div>Loading image...</div>; // or just return null if you want nothing to be rendered.
} else {
return <img src={Newman} /> // along with your error message here
}
}
A bit of a different approach, but if you have the image source in advance, you can add the image source to the main html file as a link ref with preload option. The browser will preload the image (with relatively low priority) and at the time your app will load the image, it should be cached in the browser memory.
<head>
..
..
<link rel="preload" href="<your_image_source_here>" as="image">
...
</head>
In this approach, we separate the preloading process from the code. It is more relevant when you have the image source in advance (and not dynamically) and when you don't need to cache a large amount of images (will be a bit messy to add a large list of links in the html head, although possible)
you can learn more about link preloading here: Preloading content with rel="preload"
In my case I start with an initial src attribute for my images and wanted to delay changing them after the image has been loaded by the browser, so I wrote the following hook in Typescript:
import { useEffect, useState } from 'react';
export const useImageLoader = (initialSrc: string, currentSrc: string) => {
const [imageSrc, _setImageSrc] = useState(initialSrc);
useEffect(() => {
const img = new Image();
img.onload = () => {
_setImageSrc(currentSrc);
};
img.src = currentSrc;
}, [currentSrc]);
return [imageSrc];
};
i'm trying to do a CardList items from a local data.json file using React.Js.
To load the data i'm using a map function:
const ItemsList = data.map(item=>{
return(
<li><img key={item.id} src={"assets/images/sampleImages/" + item.image}/></li>
)
})
Code - PasteBin
but i cannot get the image. No error, just a broken image icon appear.
I've try:
This solution And with URL works, but don't work with path.
Also this thread. And nothing works.
Firstly import the image like this (You can amend it accordingly)
import imageBaseURL = "./assets/images/sampleImages/";
Then inside your ItemList make use of Template Literals like this :
const ItemsList = data.map( item => {
return(
<li><img key={item.id} alt="TitleOfImage" src={`${imageBaseURL}${item.image}`}/></li>
)
})
First step:
Importing image and store it in one variable ( ExampleImg )
import ExampleImg from '../example.png';
Second step:
Inject the image as a src
<img src = { ExampleImg } />
I have an issue with a component that takes a name property for use as an avatar (replaces spaces with dashes and adds file format). This then gets used as the img src dynamically.
Works absolutely fine locally, no stuttering changing the image. When I bundle and deploy to surge.sh and change routes the image stutters. I expected this as each image needs to be downloaded initially but even after the image is cached, swapping the image is jerky. Any ideas? Or is there a better way to do this?
class Athlete extends Component {
constructor (props) {
super(props);
}
render () {
let name = this.props.name;
let imgName = name.replace(/\s+/g, '-').toLowerCase();
let imgSrc = '/img/athletes/' + imgName + '.jpg';
return (
<div className="winner__inner">
<img src={imgSrc} alt={name} className="winner__avatar"/>
<h3 className="winner__name">{name}</h3>
</div>
);
}
}
export default Athlete;
Link: http://boulder.surge.sh/ (desktop only - click one of the events)
GIF: https://i.gyazo.com/4dea5302d9671b4de0fadc2334f872da.gif
Cached images: https://i.imgur.com/xQLgIWq.png
Any help would be great, thanks!
Alright hey guys. Trying to get this clock functioning with the pictures. I have more than just the one but if I can get the one figured out I can handle the others. After much searching I found out you can't use string interpolation within an attribute but I kept it there to show I tried. The second one I think "should work" and it shows the variable i'm trying or pic0, pic1 and so on but it's a string not the actual module i'm importing at the top (in the actual app I have them all imported but cut them down for brevity on the question. Any assistance?? I'm bashing my head what is causing this issue
import React, { Component } from 'react';
import './App.css';
import './bootstrap-3.3.7-dist/css/bootstrap.min.css';
import pic0 from './0.png';
export default class Clock extends Component {
constructor(props) {
super(props);
this.incrementTime = this.incrementTime.bind(this);
this.dayInWords = this.dayInWords.bind(this);
this.state = {
clock: new Date(),
day: (new Date()).getDay(),
hours0: 0,
minutes0: 0,
seconds0: 0,
hours1: 0,
minutes1: 0,
seconds1: 0
}
}
componentWillMount() {
let intervalTimer = setInterval(this.incrementTime, 1000);
}
componentWillUnmount() {
clearInterval(this.state.intervalTimer);
}
incrementTime() {
this.setState(currentState => {
return {
clock: new Date(),
seconds1: ((new Date()).getSeconds())%10
};
});
}
render() {
return(
<div className='panel-body imgContainer'>
<img src={pic0} alt='the digit 0' />
<p>Know this one doesnt work but kept here to show I tried it</p>
<img src={`pic${this.state.seconds1}`} alt='seconds1' />
<p>I think this should work and the src is what I want as the variable that im importing at the top but its just a string not the variable.</p>
<img src={'pic' + this.state.seconds1} alt='seconds1' />
<p>This is the end goal im trying to accomplish but im trying to see if it can be done using this.state.seconds so its kind of "dynamic" and the source changes every second thus changing the image</p>
<img src={pic0} alt='seconds1' />
</div>
);
}
}
this is what i'm seeing it's the image not showing the src is the "variable" im importing at the top but it's not actually calling that variable/module sorry if my terminology is wrong i'm clearly pretty new at this.
Thanks for all the assistance!!!!
Although this was clarified in the comments, for future visitors of this post - you need to reference the imported image directly:
import pic from './myImage';
// works
<img src={ pic } />
It can be placed in the state, or some other variable, but can't be accessed via a string with the same name:
// Doesn't work
<img pic={ 'pic' } />