Dynamic Image not rendering - reactjs

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.

Related

Display element based on event fired and props passed in

I am trying, to manipulate another element, by, passing props directly to it, and then have it display itself. If I pass true/false.
Live running code:
https://codesandbox.io/s/keen-dan-rt0kj
I don't know if it's possible to have a system of objects, and based on an event, tell a parent to display a child.
App.js
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
state = {
display: false
};
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}
./components/Content.js:
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
display: props.display
};
}
render() {
const { display } = this.state;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Goal:
I want to based on a state, and based on fired event, display an element that already in store of root.
EDIT: I am aware that, this exists and can be used: import PropTypes from 'prop-types', however, I am not sure this is good practice, since it requires some parent or some other component to implement the props.
JUST Tried:
App:
<Content display={this.state.display} content={"Hello World"} />
Content:
<h3>{this.state.content}</h3>
It seems the passed in text, stored in Content state = {content: props.content} does get displayed, wheres, the boolean value does not work directly. Is there something wrong with sending in a bool ?
try this in your Content Component
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
};
}
render() {
return (
<>
{this.props.display?(
<div
id="mydiv"
className="mydiv"
>
<h3>A simple div</h3>
</div>
):null}
</>
);
}
}
The reason this may not be working is because you are initiating the state in a way that does not connect the display props after the component is initialized. This means that after the Content component is "constructed", the state of the Content and it's parent are not linked. This is because the constructor() function is only run once to initialize the state.
The best option you have is to not use the internal state of the Content component. Rather than initializing state with the display prop, just use the display prop in your render function.
Trying something like this might work
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super(props);
}
render() {
const { display } = this.props;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Also I would reccommend using state in the root:
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
constructor(props) {
super();
state = {
display: false
};
}
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}

Using STATE as html ATTR in React JSX

I am working in ReactJS, and have a URL of a photo stored in State. I want to use that photoURL to call up the image in my component render. But it when I use the normal src={this.state.photoURL} it throws an error.
Ideally, I would be able to use it as a background image in a container like this:
<div className='photo-cont' style='background-image:url({this.state.photoURL}); background-size:cover;'
I've tried this and as a normal img, with and without quotes around the curly braces, with and without the curly braces themselves.
class Foo extends Component {
state: {
photoURL: 'www.foobar.com/foo.jpg',
}
render () {
return(
<img src={this.state.photoURL}></img>
)
}
}
I keep getting the following error: 'TypeError: Cannot read property 'photoURL' of null'
It seems like you have a typo in your code. To initialize a class field (like state you should use =.
I added both an example of the photoURL as an image and as a background image of a div. Remember to set width/height/padding on the div to show the image:
class Foo extends React.Component {
state = {
photoURL: 'https://unsplash.it/400/200',
}
render () {
return(
<div>
<img src={this.state.photoURL}/>
<div style={{
width: '400px',
height: '200px',
backgroundImage: `url(${this.state.photoURL})`,
}}/>
</div>
)
}
}
ReactDOM.render(<Foo/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
class Foo extends Component {
contructor(props) {
super(props)
this.state = {
photoURL: 'www.foobar.com/foo.jpg',
}
}
render () {
return(
<img src={this.state.photoURL}></img>
)
}
}
try to use contructor() to defined your state
import logo from './logo.png';
class Foo extends Component {
render () {
return(
<img src={logo}></img>
)
}
}
Check out their documentation:
https://facebook.github.io/create-react-app/docs/adding-images-fonts-and-files

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>
);
}

React div style not updating on render

I'm trying to update the background color of a div when an array in my context is populated. On the initial render the background is being set as I would expect, however when the context is updated and a new value is pushed into the array, I can see the length increasing in the tags, however the background color set in the style doesn't seem to update.
Code below:
import React, { Component } from 'react';
import { Consumer } from '../../context';
import AlertWindow from './AlertWindow';
class AlertTab extends Component {
constructor(props){
super(props);
this.state = {
type: props.type,
active_color: props.active_color
}
}
render() {
return (
<Consumer>
{value => {
const { geofence_alarms } = value;
const { type, active_color } = this.state;
return (
<div>
<div className='alert-tab' style={{background: (geofence_alarms.length > 0 ? active_color : '#8E8E8E')}}>
<h6>{type}</h6>
<h6 style={{fontSize:'22pt', float: 'right'}}>{geofence_alarms.length}</h6>
</div>
<AlertWindow />
</div>
)
}}
</Consumer>
)
}
}
export default AlertTab;
You can see from the below images that the length of the geofence_alerts array does indeed increase:
I'm assuming this has something to do with the way styles are being loaded in React, but does anyone know the proper way I could achieve this?
Thanks in advance!
Simply put, don't use this.state for props. When properties update, a rerender will happen, but the component will not be reinitialized/remounted. Since you copy over your props to the state in the constructor, this will not be called, and your state will contain the old props that were passed in initially when the component was mounted. In this case, you can pull type and active_color straight from this.props:
import React, { Component } from 'react';
import { Consumer } from '../../context';
import AlertWindow from './AlertWindow';
class AlertTab extends Component {
render() {
return (
<Consumer>
{value => {
const { geofence_alarms } = value;
const { type, active_color } = this.props;
return (
<div>
<div className='alert-tab' style={{background: (geofence_alarms.length > 0 ? active_color : '#8E8E8E')}}>
<h6>{type}</h6>
<h6 style={{fontSize:'22pt', float: 'right'}}>{geofence_alarms.length}</h6>
</div>
<AlertWindow />
</div>
)
}}
</Consumer>
)
}
}
export default AlertTab;

Why Images not loading, when trying to load from an array in react

I have following code where i am trying to load images from Array, if i try to load a single image it works fine, but if i try to load multiple images it dosent show any image, tho my div test is in the dom.
import React, {Component} from 'react';
class Slider extends Component {
render() {
const myItems = [{source_image: '1.jpg'}, {source_image: '2.jpg'}, {source_image: '3.jpg'}];
return (
<div id="test">
{myItems.map(function (a) {
<img src={"images/"+a.source_image}/>
}
)}
</div>
);
}
}
export default Slider;
You forget return in map:
{myItems.map(function (a) {
return <img src={"images/"+a.source_image}/> // here
})
}
{myItems.map(a => <img src={"images/"+a.source_image}/>)} //this is more clear, I think

Resources