I'm having an issue getting an image to appear within my React project. I've done it before and actually copied the same exact code to put it into my project, but for some reason nothing is showing up. I looked in the console and inspected the image and it's showing that there is something there, but just not rendering somehow. Nothing I search for online has a similar issue so I'm wondering if I'm just missing something, and that's what causing it not to render.
Here is the parts of my file that pertains to my question.
import React from 'react';
import { Link } from 'react-router-dom';
import Button from '../../components/Spinner/Button';
import ATABanner from '../../../public/Images/ATAbanner-flip.png';
import ATADouble from '../../../public/Images/ATAdouble-1.png';
import ATASingle from '../../../public/Images/ATAsingle-1.png';
import '../../StyleSheets/AdContract.css';
import '../../StyleSheets/Button.css';
export default class CustomerPage extends React.Component{
constructor(props){
super(props);
this.state = {
QuoteID: this.props.match.params.id,
CustomerFirst: "",
CustomerLast: "",
CurrStep: 1,
StoreList: [],
StoresSelected: [],
AdSize: "",
AdSelected: "",
}
}
... extra stuff and methods here
AdSizeHandler(e){
console.log(e.target.id);
switch(e.target.id){
case "SINGLE": this.setState({AdSize: e.target.id});
break;
case "DOUBLE": this.setState({AdSize: e.target.id});
break;
case "BANNER": this.setState({AdSize: e.target.id});
break;
}
}
RenderAdSelected(){
let img = null;
let ad = this.state.AdSize;
if(ad == "SINGLE"){
img = (
<img id="ad-image-single" name='ADSingle' src={ATASingle} alt="" width="100%" scrolling="no"/>
)
}else if(ad == "DOUBLE"){
img = (
<img id="ad-image-double" name='ADDouble' src={ATADouble} alt="" width="100%" scrolling="no"/>
)
}else if(ad == "BANNER"){
img = (
<img id="ad-image-banner" name='ADBanner' src={ATABanner} alt="" width="100%" scrolling="no"/>
)
}
return img;
}
render(){
return(
<div id="CustomerContainer" style={{width: '100%', height: '100%'}}>
<div id="CustomerContent" className="fade-in" style={{textAlign: 'center', width: '100%', height: '100%', overflowY: 'auto'}}>
<div id="Welcome" style={{marginTop: '5%'}}>
<p style={{fontSize: '35px', fontWeight: 'bold'}}>Hello, {this.state.CustomerFirst + " " + this.state.CustomerLast}</p>
<p style={{fontSize: '20px', color: 'orange'}}><b>Your Quote Is Almost Ready!</b></p>
</div>
<div style={{marginTop: '5%', color: '#0F9D58', fontSize: '37px'}}>
<p><b>Step: {this.state.CurrStep}</b></p>
</div>
<div id="InnerContainer" style={{width: '80%', marginLeft: 'auto', marginRight: 'auto'}}>
{this.RenderStoreSelect(this.state.CurrStep)}
<div id="ad-select">
<div className="fade-in" id="ad-prompt">
<p style={{fontSize: '20px'}}><b>Please Select Your Ad Size</b></p>
</div>
<div id="ad-buttons" style={{display: 'inline-block', marginTop: '2%'}}>
<span style={{display: 'flex'}}>
<Button name="SINGLE" color="G-green" click={this.AdSizeHandler.bind(this)}></Button>
<Button name="DOUBLE" color="G-green" click={this.AdSizeHandler.bind(this)}></Button>
<Button name="BANNER" color="G-green" click={this.AdSizeHandler.bind(this)}></Button>
</span>
</div>
<div>
<img id="adImage" name='ADSingle' src={ATASingle} alt="" width="100" height="100"/>
</div>
</div>
</div>
{this.ConfirmQuote()}
</div>
</div>
)
}
}
Here is proof that it's retrieving the image:
If anyone has any idea what I'm possibly doing wrong, please let me know. Thanks.
I found out the reason for this issue. The problem is that I am in a different route than the home route '/'. I solved my problem by doing this instead: <img id="adImage" name='ADSingle' src={`/${ATASingle}`} alt="" width="100" height="100"/>
Related
I have image paths in an array and I want to display the images when I map the array. My code is as follows :
import React, { Component } from 'react';
class ItemsList extends Component {
constructor() {
super();
this.state = {
products: [
{
"name": "Item 1",
"imageURL": "../images/milk.jpg"
},
{
"name": "Item 2",
"imageURL": "../images/bread.jpg"
},
]
}
}
render() {
const { products } = this.state;
return (
<div>
<div className="row">
{
products.map((val, ind) => {
return (
<div className="card mx-2 my-2 shadow-lg p-3 mb-5 bg-white rounded" key={ind} style={{ width: '345px', alignItems: 'center' }}>
<img src={val.imageURL} className="card-img-top" style={{ height: '240px', width: '240px' }} alt="product image" /> // *** Displaying Image Here ***
<div className="card-body" style={{ backgroundColor: '#a6b0bf', width: '100%', textAlign: 'center' }}>
<h5 className="card-title">{val.name}</h5>
<br />
</div>
</div>
);
})
}
</div>
</div>
);
}
}
export default ItemsList;
The image is not displaying. I want to display the image in the map method but can't get it done. Need help.
You may need to use require:
<img src={require(`${val.imageURL}`)} className="card-img-top" />
I am creating an image grid for a website Im making using React and I wanted to add a modal functionality to view each image as a modal pop-up. For this I need to use some Vanilla JS in combination with CSS and HTML. This is the js I want to use:
// Select the modal
var modal = document.getElementById('myModal');
// Get the image inside the modal
var img = document.getElementsByClassName('image');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function(){
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Select the close button
var span = document.getElementsByClassName("close");
// Close Button
span.onclick = function() {
modal.style.display = "none";
}
How can I integrate it with the rest of the app?
EDIT:
This is the component I am working on:
import React from "react";
import "../stylesheets/Photos.scss";
const Photos = () => {
return (
<div className="photos_container">
<h1 className="photos_title">PHOTO GALLERY</h1>
<div className="row">
<div className="column">
<img className='image'src="../assets/photos_page/photo2.jpg"/>
<img className='image' src="../assets/photos_page/photo3.jpg"/>
</div>
<div className="column">
<img className='image' src="../assets/photos_page/photo4.jpg"/>
<img className='image' src="../assets/photos_page/photo5.jpg"/>
<img className='image' src="../assets/photos_page/photo6.jpg"/>
</div>
<div className="column">
<img className='image' src="../assets/photos_page/photo7.jpg"/>
<img className='image' src="../assets/photos_page/photo8.png"/>
<img className='image' src="../assets/photos_page/photo9.jpg"/>
</div>
<div className="column">
<img className='image' src="../assets/photos_page/photo10.png"/>
<img className='image' src="../assets/photos_page/photo11.jpg"/>
</div>
</div>
{/* modal */}
<div id='mymodal' className='modal'>
<span className='close'>×</span>
<img className='modal-content' id="img01"/>
<div id='caption'></div>
</div>
</div>
);
};
export default Photos;
Someone beat me to it, but I will still leave my version of the answer here in case you find it helpful. I would not select document elements in the mentioned way, because there is simpler and more declarative way. What you want to do is change this component into a stateful one, which contains a state property like "showmodal". When it is true, the modal should be shown. Then you can toggle the state and set the image which was clicked on by using this.setState({ showmodal: true, slectedImage: yourImage }) in your onClick function. A simple absolutely positioned container should do the trick for the modal container.
Here is an example of what such a component would look like.
const images = [
{
uri:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTm3CuNzOrmWhos3MXI0v_KkyO_xrZ5Y8hFxSYGj_6OtUygZUUX"
},
{
uri:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQR_Fg_lMrPjMa1duHXnvFnZOtsn883LGLD7c2-CwKdfFXAoveQnQ"
}
];
class App extends React.Component {
state = {
showmodal: false,
selectedImage: undefined
};
render() {
//
return (
<div style={{ height: "100vh"}}>
{images.map(i => (
<img
key={i.uri}
src={i.uri}
style={{ margin: 5 }}
onClick={() => this.setState({ showmodal: true, selectedImage: i })}
/>
))}
{this.state.showmodal &&
<div
onClick={() => this.setState({ showmodal: false })}
style={{
display: 'flex',
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: "rgba(0,0,0,0.5)",
justifyContent: 'center', alignItems: 'center'
}}
>
<div style={{ height: 300, width: 500, backgroundColor: '#fff' }}>
<img src={this.state.selectedImage.uri} style={{ flex: 1}} />
<h3>Place any content here</h3>
</div>
</div>}
</div>
);
}
}
React.render(<App />, document.getElementById("app"));
I did not refactor out the styles so you can see what each div is doing as a super basic example which you can check out in codepen. Also, I agree with viz above in trying to refactor you columns so that you can render them the exact same way, and reduce duplication.
Hope it helps!
Everything in react is javascript, so
<div style={{display: this.state.showModal ? 'block' : 'none' }}>
<span onClick={() => {this.state.showModal = false;}}>×</span>
<img src={this.state.currentImage}/>
<div>{this.state.currentCaption}</div>
</div>
and then set respective currentImage and currentCaption with setState upon the image click.
You should also consider programmatically composing the column & images' jsx so that it can be concise.
I am trying to grab the maxresdefault of multiple YouTube thumbnails. Some YouTube videos simply don't have a high res thumbnail photo so I want to catch that with an onError prop on an img element. For some reason my function is not triggering when I get the 404 img error. Any ideas? Thanks in advance.
class FeaturedVideo extends Component<Props> {
addDefaultSrc = (e) => {
e.target.src = this.props.background.replace("maxresdefault", "hqdefault")
}
renderVideo = (props) => (
<div
style={{
width: "100%",
height: "100%",
backgroundSize: "contain",
}}
className="featured-community-video"
>
<img onError={this.addDefaultSrc} src={props.background} alt="" />
<div className="featured-community-video-title">
<h2 style={{ fontSize: "0.8em" }}>WATCH</h2>
<h1 style={{ fontSize: props.titleFontSize }}>{props.title}</h1>
</div>
</div>
)
render() {
return (
<div
key={this.props.postId}
style={{
width: this.props.width,
height: "50%",
}}
className="featured-community-video-container"
>
<Link to={routeCodes.POST_DETAILS(this.props.postId)}>
{this.renderVideo(this.props)}
</Link>
</div>
)
}
}
To achieve this, I would suggest rendering the <img /> based on the state of your <FeatureVideo/> component.
You could for instance, create an Image object, attempt to load the background image and by this, reliably determine if the image fails to load. On the images success or failure to load, you would then setState() on your <FeaturedVideo/> component with the appropriate background value which would instead be used to rendering you actual <img/> element:
class FeaturedVideo extends Component<Props> {
componentDidMount() {
if(this.props.background) {
// When component mounts, create an image object and attempt to load background
fetch(this.props.background).then(response => {
if(response.ok) {
// On success, set the background state from background
// prop
this.setState({ background : this.props.background })
} else {
// On failure to load, set the "default" background state
this.setState({ background : this.props.background.replace("maxresdefault", "hqdefault") })
}
});
}
}
// Update the function signature to be class method to make state access eaiser
renderVideo(props) {
return <div
style={{
width: "100%",
height: "100%",
backgroundSize: "contain",
}}
className="featured-community-video">
{/* Update image src to come from state */}
<img src={this.state.background} alt="" />
<div className="featured-community-video-title">
<h2 style={{ fontSize: "0.8em" }}>WATCH</h2>
<h1 style={{ fontSize: props.titleFontSize }}>{props.title}</h1>
</div>
</div>
}
render() {
return (
<div
key={this.props.postId}
style={{
width: this.props.width,
height: "50%",
}}
className="featured-community-video-container"
>
<Link to={routeCodes.POST_DETAILS(this.props.postId)}>
{this.renderVideo(this.props)}
</Link>
</div>
)
}
}
Hope that helps!
When the page loads initially the header should not be visible but when a user begins to scroll the header should appear.
What do I expect to see?
The header should not be visible until a user begins to scroll
What do I see now
The header is showing when the page first loads and it is not supposed to be showing. It is only not working as expected in Chrome, and it is working in Safari.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hide: false
};
}
handleHover = () => {
this.setState({
hide: true
});
};
componentDidMount() {
window.addEventListener("scroll", this.handleHover);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.handleHover);
}
render() {
return (
<div>
{this.state.hide ? (
<div
style={{
width: "100%",
height: "120px",
margin: "0 auto",
position: "absolute"
}}
>
<div
style={{
zIndex: "0",
position: "absolute",
marginLeft: "120px",
marginTop: "6px"
}}
>
<img className="Logo" src={Logo} alt="logo" />
</div>
<div className="menuContainer">
<nav>
<Link to="/" className="linkTitle" href="">
Home
</Link>
<Link to="/shop" className="linkTitle" href="">
Shop
</Link>
<a className="linkTitle" href="#aboutus">
About
</a>
<a className="linkTitle" href="">
Contact Us
</a>
<a className="linkTitle" href="">
As seen
</a>
</nav>
</div>
</div>
) : null}
<div className="picContainer">
<div
style={{ backgroundImage: `url(${hairImage})` }}
className="picSection one"
/>
<div className="picSection two" />
<div className="picSection three" />
<div className="picSection four" />
<div className="picSectionL five" />
</div>
</div>
);
}
}
https://codesandbox.io/s/zlyqyvjzjl
There you go. Make sure you can actually scroll. If you div is too small to scroll, it won't trigger the event.
{this.state.hide ? null : <div>some item</div>}
Here is the full code:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hide: true
};
}
handleHover = () => {
console.log("hello");
this.setState({
hide: false
});
};
componentDidMount() {
window.addEventListener("scroll", this.handleHover);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.handleHover);
}
render() {
return (
<div style={{ height: "2000px" }}>
{this.state.hide ? null : (
<div
style={{
width: "100%",
height: "120px",
margin: "0 auto",
position: "absolute"
}}
>
<div
style={{
zIndex: "0",
position: "absolute",
marginLeft: "120px",
marginTop: "6px"
}}
>
logo
</div>
</div>
)}
<div className="picContainer">hello</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I am using infinite scroll plugin for react.js and for some reason it is not working the way it is supposed to work.
The problem is that all the requests are made at once when the page loads, and not like for example a request should be made for each time I scroll.
My code looks like below:
import React from 'react';
import {Route, Link} from 'react-router-dom';
import FourthView from '../fourthview/fourthview.component';
import {withRouter} from 'react-router';
import {Bootstrap, Grid, Row, Col, Button, Image, Modal, Popover} from 'react-bootstrap';
import traineeship from './company.api';
import Header from '../header/header.component';
import InfiniteScroll from 'react-infinite-scroller';
require('./company.style.scss');
class Traineeship extends React.Component {
constructor(props) {
super(props);
this.state = {
companies: [],
page: 0,
resetResult: false,
hasMore: true,
totalPages: null,
totalElements: 0,
};
}
componentDidMount() {
this.fetchCompanies(this.state.page);
}
fetchCompanies = page => {
let courseIds = '';
this.props.rootState.filterByCourseIds.map(function (course) {
courseIds = courseIds + '' + course.id + ',';
});
traineeship.getAll(page, this.props.rootState.selectedJob, courseIds.substring(0, courseIds.length - 1), this.props.rootState.selectedCity).then(response => {
if (response.data) {
const companies = Array.from(this.state.companies);
if(response.data._embedded !== undefined){
this.setState({
companies: companies.concat(response.data._embedded.companies),
totalPages: response.data.page.totalPages,
totalElements: response.data.page.totalElements,
});
}
if (page >= this.state.totalPages) {
this.setState({hasMore: false});
}
} else {
console.log(response);
}
});
};
render() {
return (
<div className={"wrapperDiv"}>
{/*{JSON.stringify(this.props.rootState)}*/}
<div className={"flexDivCol"}>
<div id="header2">
<div style={{flex: .05}}>
<img src="assets/img/icArrowBack.png" onClick={() => this.props.history.go(-1)}/>
</div>
<div style={{flex: 3}}>
<Header size="small"/>
</div>
</div>
<div id="result">
<div className={"search"}>
<h2 style={{fontSize: 22}}>Harjoittelupaikkoja</h2>
<p className={"secondaryColor LatoBold"} style={{fontSize: 13}}>{this.state.totalElements} paikkaa löydetty</p>
</div>
<div className={"filters"}>
<h5 style={{marginTop: '30px', marginBottom: '10px'}} className={"primaryColor"}>
<strong>Hakukriteerit</strong></h5>
{
this.props.rootState.filters.map((filter, key) => (
<div key={key} className={"filter"}>{filter.title}</div>
))
}
</div>
<div className={"searchResults"}>
<h5 style={{marginTop: '30px', marginBottom: '10px'}} className={"primaryColor"}>
<strong>Hakutulokset</strong></h5>
<InfiniteScroll
pageStart={0}
loadMore={this.fetchCompanies}
hasMore={this.state.hasMore}
loader={<div className="loader" key={0}>Loading ...</div>}
useWindow={false}
>
{
this.state.companies.map((traineeship, key) => (
<div id={"item"} key={key}>
<div className={"companyInfo"}>
<div className={"heading"}>
<div id={"companyDiv"}>
<p className={"LatoBlack"} style={{
fontSize: '18px',
lineHeight: '23px'
}}>{traineeship.name}</p>
</div>
{
traineeship.mediaUrl == null
? ''
:
<div id={"videoDiv"}>
<div className={"youtubeBox center"}>
<div id={"youtubeIcon"}>
<a className={"primaryColor"}
href={traineeship.mediaUrl}>
<span style={{marginRight: '3px'}}><Image
src="http://www.stickpng.com/assets/images/580b57fcd9996e24bc43c545.png"
style={{
width: '24px',
height: '17px'
}}/></span>
<span> <p style={{
fontSize: '13px',
lineHeight: '24px',
margin: 0,
display: 'inline-block'
}}>Esittely</p></span>
</a>
</div>
<div id={"txtVideo"}>
</div>
</div>
</div>
}
</div>
<div className={"location"}>
<div id={"locationIcon"}>
<Image src="assets/img/icLocation.png"
style={{marginTop: '-7px'}}/>
</div>
<div id={"address"}>
{
traineeship.addresses.map((address, key) => {
return (
<a href={"https://www.google.com/maps/search/?api=1&query=" + encodeURI("Fredrikinkatu 4, Helsinki")}>
<p key={key} className={"primaryColor"} style={{fontSize: '13px'}}>{address.street}, {address.city}</p>
</a>
)
})
}
</div>
</div>
<div className={"companyDescription"}>
<p className={"secondaryColor"} style={{
fontSize: '14px',
lineHeight: '20px'
}}>{traineeship.description}</p>
</div>
<div>
{
traineeship.images.map((image, key) => {
return (
<img id={"thumbnail"} width={"100%"}
src={image.url}
style={{
width: '80px',
height: '80px',
marginRight: '10px',
marginBottom: '10px'
}}
alt=""
key={key}
/>
)
})
}
</div>
<div className={"companyContacts"} style={{marginTop: '20px'}}>
<p className={"contactInfo"}>URL: {traineeship.website}</p>
<p className={"contactInfo"}>Email: {traineeship.email}</p>
<p className={"contactInfo"}>Puh: {traineeship.phonenumber}</p>
<p className={"contactInfo"}>Contact: {traineeship.contact}</p>
</div>
</div>
</div>
))
}
</InfiniteScroll>
</div>
</div>
</div>
</div>
);
}
}
export default withRouter(Traineeship);
What can I do so I can eliminate all the request are made when the page is load, I mean this is even worse sending let say 20 request one after another within a second or so.
Any suggestion what is wrong with my code?
by removing useWindow={false} it is working now!
Update: Haven't seen that you are using react-infinite-scroller. If you want to build the loader yourself, see my previous answer. With the plugin you can set a threshold.
The answer lies in here: Question: Infinite Scrolling
What you basically need to do is to set a variable in state, isLoading: false, and change it when data comes in via fetch, when data loading done set it back to false. In your infinite scroll function check (this.state.isLoading).