Reputation: 2836
I'm a beginner and are reading lots of code and now I wonder about the below code
I understand what this code is doing what I need clarification on is the code flow.
I see images loading when I run it:
App
Component start to render with out images if it takes time? If so I dont see any setState
that will notify App
. I probably get it wrong!This code is from this Sandbox.
This is index.js
import React from "react";
import ReactDOM from "react-dom";
import Masonry from "./Masonry";
import VerticalMasonry from "./VerticalMasonry";
import { sample, uniqueId } from "lodash";
import PlaceholderImages from "./PlaceholderImages";
import ItemRenderer from "./ItemRenderer";
PlaceholderImages().then(images => {
function addItems(amount = 10) {
return new Array(amount).fill("").map(i => {
const id = uniqueId();
const image = sample(images);
const width = 480;
const height = Math.round((480 / image.width) * image.height);
const imageUrl = `https://picsum.photos/${width}/${height}?image=${
image.id
}`;
return {
id,
key: id,
ratio: 1 / (image.width / image.height),
backgroundImage: `url(${imageUrl})`,
background: `rgb(${Math.ceil(Math.random() * 256)}, ${Math.ceil(
Math.random() * 256
)}, ${Math.ceil(Math.random() * 256)})`,
title: "Lorem ipsum dolor sit amet",
description:
"At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
};
});
}
let Items = addItems();
class App extends React.Component {
state = {
columns: 3,
items: Items,
gutter: 16,
outerGutter: true,
debug: true,
vertical: true
};
addItems() {
this.setState({
items: this.state.items.concat(addItems(20))
});
}
render() {
const {
items,
width,
gutter,
outerGutter,
debug,
vertical,
fullscreen
} = this.state;
const LeComponent = vertical ? Masonry : VerticalMasonry;
return (
<div>
<div
style={{
position: fullscreen && "absolute",
zIndex: 2
}}
>
<label htmlFor="gutter">Gutter</label>
<input
id="gutter"
type="number"
step={1}
min={0}
max={32}
value={gutter}
onChange={e => {
this.setState({
gutter: parseInt(e.target.value)
});
}}
/>
<button
onClick={() => this.setState({ outerGutter: !outerGutter })}
>
Outer Gutter: {outerGutter ? "On" : "Off"}
</button>
<button onClick={() => this.setState({ debug: !debug })}>
debug
</button>
<button onClick={() => this.setState({ vertical: !vertical })}>
{vertical ? "Vertical" : "Horizontal"}
</button>
<button onClick={() => this.setState({ width: 360 })}>360</button>
<button onClick={() => this.setState({ width: 480 })}>480</button>
<button onClick={() => this.setState({ width: 640 })}>640</button>
<button onClick={() => this.setState({ width: 728 })}>728</button>
<button onClick={() => this.setState({ width: 960 })}>960</button>
<button onClick={() => this.setState({ width: "100%" })}>
100%
</button>
<button onClick={() => this.setState({ fullscreen: !fullscreen })}>
{fullscreen ? "Fullscreen off" : "Fullscreen on"}
</button>
</div>
<div
style={{
width,
height: !fullscreen && 600,
position: fullscreen ? "initial" : "relative",
margin: "0 auto"
}}
>
<LeComponent
infinite
items={items}
itemRenderer={ItemRenderer}
gutter={gutter}
outerGutter={outerGutter}
extraPx={0}
debug={debug}
rows={{
0: 1,
320: 2,
480: 3,
640: 4
}}
cols={{
0: 1,
360: 2,
640: 2,
960: 3,
1280: 4,
1400: 5,
1720: 6,
2040: 7,
2360: 8
}}
onEnd={() => {
this.addItems();
}}
/>
<style>
{`body {
background-color: white;
}`}
</style>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
});
This is the PlaceholderImages.js
import axios from "axios";
import { sampleSize } from "lodash";
export default async () => {
return new Promise((resolve, reject) => {
axios.get("https://picsum.photos/list").then(res => {
console.log(res.data[0]);
return resolve(sampleSize(res.data, 50));
});
});
};
Upvotes: 2
Views: 96
Reputation: 34
PlaceholderImages().then(images => {...
The first thing entering your stack here is the method PlaceholderImages
. Thus, you should look at its code.
You will see it returns a new Promise that takes two arguments: 2 callback functions, one in case of success (resolve) and the other in case of failure (reject) of your API request. The API request happens when your perform a HTTP Request with the method GET using axios
(a 3rd party library).
Again, you have an asynchronous function and the .then()
method is only invoked once axos.get()
returns something. If it never returns anything, you will never execute the then()
function.
At this point, your stack (LIFO service discipline) will have the following methods to execute:
PlaceholderImages() -> anonymous function()* -> new Promise() -> axios.get();
PlaceholderImages()
won't be executed until all the other methods are executed. If the axios.get()
method fails to gather the desired data, once you are back to the PlaceholderImages().then()
part of the code, you won't have any images to render. Thus, nothing will be rendered anyway.
Upvotes: 2