How to change image source using state variable with React.js - reactjs

I have an image component with the following html:
<img src={this.state.img_path} onClick={this.getNew} alt={this.state.alt} width={150} />
Initially I set the image to Blank which I import from an image:
import Blank from './images/blank.jpg';
then I use Blank to initialize my state variable.
When the image is clicked, getNew is called, where I set the state variable img_path to a relative image path:
this.setState({img_path: item.ImgPath, alt: item.alt});
The function getNew gets called without an issue and executes without an error but the image does not get displayed, just an icon and alt value. How do i do dynamic image source switch in React?
Update:
here is my class
import React, { Component } from 'react';
import Blank from './images/blank.jpg';
class myImg extends Component {
constructor(props) {
super(props);
this.state = {
img_path: Blank,
alt: 'blank',
};
this.getNew = this.getNew.bind(this);
}
getNew() {
const items = [{ItemName: 'test1', ItemImg: './images/test1.jpg'}, {ItemName: 'test2', ItemImg: './images/test2.jpg'} ];
var item = items[math.floor(Math.random() * items.length)];
this.setState({ img_path: item.ItemImg,
alt: item.ItemName });
}
render() {
return (<div>
<img src={this.state.img_path} onClick={this.getNew} alt={this.state.alt} width={150} />
</div>);
}
}
export default myImg;

I figured out the fix. I used require. At first it did not work but then I wrapped the image path state variable in ${}. Basically I changed
<img src={this.state.img_path} onClick={this.getNew} alt={this.state.alt} width={150} />
to
<img src={require(`${this.state.img_path}`)} onClick={this.getNew} alt={this.state.alt} width={150} />
that got the image to be displayed

Related

Dynamic Image not rendering

I want to dynamically render images, but nothing is show up. Here is the starter code that I am using from Import image dynamically in React component.
import React, { Component, Fragment } from 'react';
class Test extends Component{
constructor(props){
super(props);
this.state = {
image: "",
}
this.loadImage = this.loadImage.bind(this);
}
componentDidMount(){
this.loadImage("Test")
}
loadImage = imageName => {
import(`../assets/${imageName}.png`).then(image => {
this.setState({
image
});
});
};
render() {
const { image } = this.state;
return (
<Fragment>
hello
{image && <img src={image} alt="" />}
</Fragment>
);
}
}
export default Test;
Hello renders, but the image is no where to be seen. Any thoughts
You can add the string directly into your image state, without rendering it asynchronous. I don't think the import statement is needed. Once you have the string you could use a similar logic you have already in place with the image but instead if you are using webpack this might work:
<div
style={{
backgroundImage: `url(${image})`,
height: "106px"
}}
If you are not using webpack, than you can add the image state in the src attribute.

Show a React Skeleton Loader until a image load completely

I Have a react-loading-skeleton in my component, i have a static image in my page that i loaded using img tag, i want to show a skeleton component until the image loads.
I tried react.lazy and suspense but it only shows until the component load not works until image loads completely.
import React from 'react';
export default class SlideItems extends React.Component {
render() {
return (
<div>
<img src={require("./someImg.jpg")}/>
</div>
);
}
}
Start by adding constructor and state to class:
constructor(props) {
super(props);
this.state = {
image: '',
}
}
You can then add onLoad property to image tag like this:
<img src={require("./someImg.jpg")} onLoad={this.handleImageLoaded.bind(this)}/>
And create function that handles image loading:
handleImageLoaded() {
this.setState({ image: 'loaded' });
}
Then in render you can do something like this:
render() {
return (
<div>
{!this.state.image &&
<SkeletonComponent/>
}
<img src={require("./someImg.jpg")} onLoad={this.handleImageLoaded.bind(this)}/>
</div>
);
}

ReactJS Load Images on Click

Hello im trying to make an image changer. at first load i should get displayed the first image in the state. if click on the button the image should be changed to second and so on. the problem right now is get displayed both images with buttons
here is my bin : enter link description here
Because you display the 2 image in your renderer.
Heres an idea how to do it (with no animation, I dont know the CSSTransitionGroup component). Just replace your main.js code withthe following
import React from 'react'
import {render} from 'react-dom'
import { CSSTransitionGroup } from 'react-transition-group'
class FadeImage extends React.Component {
constructor(props) {
super(props);
this.state = {
images: [
'http://via.placeholder.com/350x150',
'http://via.placeholder.com/350x151'
],
currentImage: 0
};
}
fadeImage(e) {
e.preventDefault();
this.setState({currentImage: (this.state.currentImage + 1) % this.state.images.length})
}
render() {
return (
<div className="image">
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}
>
<section>
<button className="button" onClick={this.fadeImage.bind(this)}>Click!</button>
<img src={this.state.images[this.state.currentImage]}/></section>
</CSSTransitionGroup>
</div>
);
}
}
render(<FadeImage />, document.querySelector('#app'))
http://bl.ocks.org/piotrf/1b7b14b0c2bfbfe1f1ef this is almost exactly what you want. You can just get rid of the parts you dont need and change the buttons to the images you want

can't get component to show up with react-images?

I keep getting null return from this component. What am I Missing???
import React from 'react';
import Lightbox from 'react-images';
const IMAGES = [
{ src: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" },
{ src: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_b.jpg" },
{ src: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_b.jpg" }
];
class ImagesRow extends React.Component {
constructor(props){
super(props);
this.onClose = this.onClose.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
}
onClose(){
}
gotoNext(){
}
gotoPrevious(){
}
render(){
return (
<Lightbox
images={IMAGES}
onClose={this.onClose}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
/>
);
}
}
This results in an empty div. Is there a required prop I'm missing?
http://jossmac.github.io/react-images/#getting-started
It is not obvious from the documentation, but react-images will not render a grid/or a gallery of your images. It will only render the Lightbox component once a image is clicked.
So, in order to get what you want (which is a gallery of some kind, AND the light box component applied to images of that gallery, then you need more than just 'react-images'. You can render the images on their own, or with another gallery/grid npm library.
For example you can render an array of images with just the normal <img> tag. BUT, be sure that each image has the "onClick" set to be a function that opens the Lightbox. see below:
...
<Grid imagesArray={thumbs} onClick={this.openLightbox.bind(this)} columns={3} padding={3} />
<Lightbox
images={images}
isOpen={this.state.lightboxIsOpen}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
onClose={this.closeLightbox}
currentImage={this.state.currentImage}
/>
I believe you need isOpen. Try
return (
<Lightbox
isOpen
images={IMAGES}
onClose={this.onClose}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
/>
);

Conditional List in ReactJS Based On State

I am pretty new to React JS and I am just wondering how I can filter what my component renders based on the state of my prop.
So I have the following component that allows me to select a certain brand and store it as a prop:
var React = require('react');
import Select from 'react-select';
class VehicleSelect extends React.Component {
constructor(props) {
super(props);
this.state = { brandSelect: ""};
}
_onChange(value) {
//console.log(value) - just to see what we recive from <Select />
this.setState({brandSelect: value}, () => {
console.log(this.state.brandSelect);
});
}
render() {
var options = [
{ value: 'Volkswagen', label: 'Volkswagen' },
{ value: 'SEAT', label: 'SEAT' },
{ value: 'SKODA', label: 'SKODA' }
];
return (
<Select
name="form-field-name"
value={this.state.brandSelect}
options={options}
placeholder="Select a brand"
searchable={false}
onChange={this._onChange.bind(this)}
/>
)
}
};
// Export our component
export default VehicleSelect;
This component works as expected however I am having issues when it comes to taking the brandSelect prop and conditionally deciding what my component should render.
Here is my details component:
var React = require('react');
import { If, Then, Else } from 'react-if';
import VehicleSelect from './vehicle-select.js';
// Vehicle Description Component
const VehicleDetail = (props) => {
return (
<If condition={ this.state.brandSelect === props.vehicle.brand.name }>
<div className="col-flex-md-3 col-flex-sm-4 col-flex-xs-6 col-flex-media-query">
<div className="vehicle-container">
<img src={"https://s3-eu-west-1.amazonaws.com/pulman-vw-images/uploads/images/thumbnails/" + props.vehicle.offers[0].image.name} />
<h4 className="vehicle-title">
{props.vehicle.model.name}
</h4>
<div className="row-flex">
<div className="col-flex-xs-12 btn-container">
Learn More
</div>
</div>
</div>
</div>
</If>
);
};
// Export our component
export default VehicleDetail;
As you can see it constructs a HTML container with data. I have also added a conditional statement (react-if on GitHub) to try and render data that matches the option that was selected in my VehicleSelect component however this doesn't seem to work. I get the following error:
Warning: There is an internal error in the React performance measurement code. Did not expect componentDidUpdate timer to start while render timer is still in progress for another instance.
Here is my component that iterates over my VehicleDetail component and supplies data to it:
var React = require('react');
// Vehicle List Componen
import VehicleDetail from './vehicle-detail.js';
// Create our component
const VehicleList = (props) => {
// Just add props.vehicle to access API data instead of static
const RenderedVehicles = props.vehicles.map(vehicle =>
<VehicleDetail key={vehicle.slug} vehicle={vehicle} />
);
return (
<div className="row-flex center-xs">
{RenderedVehicles}
</div>
);
};
// Export our component
export default VehicleList;
So my question is where am I going wrong? As I am new to ReactJS I am unsure how I can render components based on the state that has been selected. All I am trying to do is show data that matches the brandSelect prop in my VehicleSelect component. If the brandSelect prop is equals "" then I would like to render all of the data that is mapped in my VehicleList component.
Thanks
You cannot use this.state.brandSelect in the Details component
Since your details component is setup and brandselect is present in the parent component too

Resources