Reputation: 2079
Here's the code:
export default class Collage extends React.Component {
constructor() {
super();
this.state = {
images: [
<this.Image src="" />,
],
};
}
Image = ({ src }) => (
<img className="collage__img" alt="" src={src} onTransitionEnd={evt => evt.target.remove()} />
);
render() {
return (
<div className="collage">
{this.state.images}
</div>
);
}
}
All I want is to generate a list of images in .collage
block before everything is rendered. As you see, I tried to create images in the constructor. But this way I get an error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
But if I declare Image
in the constuctor (without using this
) everything works fine. Such a strange behavior.
Could you tell, is there another way to generate data before render?
Upvotes: 0
Views: 891
Reputation: 1953
Create your Image component class outside of College.js. Also remember to add in a "key" attribute on JSX which are stored in array to help react run faster.
Image.js
import React from "react";
const Image = ({ src }) => (
<img
className="collage__img"
alt=""
src={src}
onTransitionEnd={evt => evt.target.remove()}
/>
);
export default Image;
College.js
import React from "react";
import Image from "./Image";
export default class Collage extends React.Component {
constructor() {
super();
this.state = {
images: [
<Image
key="a356f8ff-0fc4-4c00-afb4-8ce60fcc210e"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/1200px-Test-Logo.svg.png"
/>
]
};
}
render() {
return <div className="collage">{this.state.images};</div>;
}
}
App.js
import React from "react";
import "./styles.css";
import Collage from "./College";
export default function App() {
return (
<div className="App">
<Collage />
</div>
);
}
Upvotes: 1
Reputation: 496
I don't know why you want to put your components in the state but this is not optimized. I think the best way to do that is somethink like this:
export default class Collage extends React.Component {
constructor() {
super();
this.state = {
images: [
{src: ""}
],
};
}
Image = ({ src }) => (
<img className="collage__img" alt="" src={src} onTransitionEnd={evt => evt.target.remove()} />
);
render() {
return (
<div className="collage">
{this.state.images.map(this.Image)}
</div>
);
}
}
Upvotes: 1
Reputation: 17494
I don't know why you don't put <Image />
as separate component since it doesn't depend on anything in your class context as below:
const Image = ({ src }) => (
<img className="collage__img" alt="" src={src} onTransitionEnd={evt => evt.target.remove()} />
);
class Collage extends React.Component {
constructor(props) {
super(props);
this.state = {
images: [
<Image src="" />
],
};
}
render() {
return (
<div className="collage">
{this.state.images}
</div>
);
}
}
Upvotes: 1
Reputation: 80
You can use react lifecycle method componentWillMount()
which will generate a list of images in .collage block before everything is rendered.
Upvotes: -1