Show a React Skeleton Loader until a image load completely - reactjs

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

Related

React Component crashes on reload

I have a notes-list component that gets the notes data as props from the main component.
Inside the notes-listcomponent, there is a notes-item component which has a dynamic route that loads notesItem-page. So, for every notes-item there is a dynamic url for it's respective notesItem-pagewhich has all the details about the notesItem object. I use Link from react-router-dom
The notes-list component looks like this:
export class NotesList extends Component {
constructor(props) {
super(props);
}
render() {
const { isLoggedIn } = this.props.loggedInContext;
return (
<div className="notes-list">
{this.props.notes.map((notesItem) => (
<Link
to={{
pathname: `${notesItem.slug}`,
id: notesItem._id,
}}
style={{
textDecoration: "none",
color: "#fea82f",
}}
>
<NotesItem notes={notesItem} />
</Link>
))}
</div>
);
}
}
export default loggedInContext(NotesList);
This successfully redirects me to the NotesItem-page with the correct props and inside the notesItem-page I get the receive the id of the object that I had passed as props and make an API call with that particular id in ComponentDidMount() method.
This works perfectly. However, it crashes on reload. It gives the following error:
I am guessing it is because of ComponentDidMount works only once,but I do not seem to find an alternate solution to this problem.
The notesItem-page component looks like this:
export class notesItemPage extends Component {
constructor(props) {
super(props);
this.state = {
notesItem: [],
};
}
componentDidMount() {
fetch(`http://localhost:5000/api/v1/notes/fetch/${this.props.location.id}`)
.then((notesItem) => notesItem.json())
.then((notesItem) =>
this.setState({ notesItem: notesItem.data, isLoaded: true })
);
}
render() {
const { notesItem } = this.state;
return (
<div className="notesItem-details">
<h1> {notesItem.title} Notes</h1>
</div>
);
}
}
export default notesItemPage;
It would be great if anyone could help me with this, thanks!
Issue is here:
<h1> {notesItem.title} Notes</h1>
here the notesItem is coming from an axios call and this data is not available on the time of first component render and this is causing the issue ( app crash ).
So change this:
<h1> {notesItem.title} Notes</h1>
to
<h1> { notesItem && notesItem.title } Notes</h1> // use it when it is available from axios call

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.

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

Rendering an image in React from this.props

I have an react application, that I created with Create-React-App. My objective is when a user clicks on an image, the image changes. So, I want the image to come from the props.
For some reason, this code does not work.
<img alt="mug shot" src={this.props.photo} />
However, this works
<img alt="mug shot" src={require('../../Assets/Photos/Four.png')}/>
What am I doing wrong here?
I assume you are bundling your app using Webpack. Probably, you might be using a file-loader/url-loader to process the image. So, when you require something that ends with image file extension, webpack runs the contents of that file through this loader. For more information, check https://survivejs.com/webpack/loading/images/
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
img:'https://www.codeproject.com/KB/GDI-plus/ImageProcessing2/img.jpg'
}
this.changeImg = this.changeImg.bind(this);
}
changeImg() {
this.setState({
img:'http://www.apicius.es/wp-content/uploads/2012/07/IMG-20120714-009211.jpg'
})
}
render() {
return(
<div>
<ImageChande change={this.changeImg} src={this.state.img} />
</div>
);
}
}
class ImageChande extends React.Component {
render() {
return(
<div>
<img onClick={this.props.change} alt="something" src={this.props.src} />
</div>
);
}
}

React Component Image Issue

My image Component won't seem to actually put the image in, the URL is correct as I can add it by physically adding the HTML into the page.
The component seems to be failing. I tried what I found at http://facebook.github.io/react/docs/jsx-in-depth.html#attribute-expressions
but it did not help.
export default class mainLogo extends React.Component {
render() {
return (
<div>
<img src = {'/src/app/assets/images/home/mainLogo.png'}/>
</div>
);
}
}
The class name should start with a capital letter (MainLogo) and you shouldn't use {} on the src, because you are sending the img url directly to the src. It's not a variable or state.
This should work:
export default class MainLogo extends React.Component {
render() {
return (
<div>
<img src='/src/app/assets/images/home/mainLogo.png' />
</div>
);
}
}

Resources