I am trying to pass my state of thumbnail URLs that are saved to an array state. But when evaluating in my Netflix component videos is empty? When I console it, it returns In tile {"videos":[]}
Render
return (
<div className="explore">
<div className="row">
<NetflixTile videos={this.state.thumbnail} />
</div>
</div>
);
Constructor
constructor(props) {
super(props);
this.props.getVideos();
this.state = {
thumbnail: []
};
}
DidMount EDITED
componentDidUpdate() {
console.log("Component updated?");
let i = 0;
if (this.props.videos == null) {
console.log("It's null");
} else {
const videos = this.props.videos.video.map(video => {
<h5 key={video._id}>{video.thumbnail}</h5>;
this.state.thumbnail[i] = video.thumbnail;
console.log(this.state.thumbnail);
i++;
});
}
}
Netflix component added into Render
const NetflixTile = videos => {
console.log("In tile " + JSON.stringify(videos.videos));
if (videos.length != null) {
for (let i = 0; videos > i; i++) {
return (
<div className="row__inner">
<div className="tile">
<div className="tile__media">
<img
className="tile__img"
id="thumbnail"
src={videos[i]}
alt=""
/>
</div>
</div>
</div>
);
}
} else {
return (
<div>
<h1>
You have not yet uploaded any STEM content. Go to your dashboard page
and click Upload to add to this library.
</h1>
</div>
);
}
};
export default NetflixTile;
OK, since you've got more or less working solution, let me update my answer with some suggestions then :)
Asynchronous calls (e.g. fetch) should be performed in componentDidMount
(it is true until React's Suspense and async stuff is landed);
If you're not modifying videos' state of the parent component - use props directly, no need to bother with any state here at all.
In another case, keep in mind that componentDidUpdate
will be called after each prop change or state change. Previously, I'd suggest using a componentWillReceiveProps
for this kind of logic. But with React 16 you can use getDerivedStateFromProps
instead. Here is what official docs are suggesting:
If you want to “reset” some state when a prop changes, consider either making a component fully controlled or fully uncontrolled with a key instead.
As you can see, it is better to handle such comparison logic (e.g. props.videos !== state.videos
) outside of component and make this component fully controlled, so it renders props directly and updates only when new props are received.
Try to minimize setState
calls, however, you might not notice a big difference even with your current solution - it is because of React is batching state updates.
In JSX, it is better to use Array.prototype.map
and ternary operators instead of for
loops and if
statements. Prefer working with value transformations rather than imperative statement jumping.
Applying these suggestions it can end up like this:
class VideosParentComponent extends React.Component {
static getDerivedStateFromProps(props, state) {
if (props.videos !== state.videos) {
return { videos: props.videos }
}
return null
}
state = { videos: [] }
componentDidMount() {
this.props.getVideos()
}
render() {
const thumbnails = this.state.videos.video.map(video => video.thumbnail)
return (
<div className="explore">
<div className="row">
{thumbnails.length !== 0
? <NetflixTitle videos={thumbnails} />
: (
<div>
<h1>
You have not yet uploaded any STEM content. Go to your dashboard page
click Upload to add to this library.
</h1>
</div>
)}
</div>
</div>
)
}
}
const NetflixTitle = ({ videos }) => (
<div className="row__inner">
{videos.map(x => (
<div key={x} className="tile">
<div className="tile__media">
<img
id={`thumbnail_${x}`}
src={x}
className="tile__img"
alt=""
/>
</div>
</div>
))}
</div>
)
You're passing videos as a prop in JSX, not as a function parameter. This is why you should retrieve it as a key in props in a destination component.
const NetflixTitle = ({ videos }) => { // rest of the code
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments