Reputation: 3760
I have a class component:
import React, { Component, Fragment } from 'react';
import ReactPlayer from 'react-player';
import storage from '../../utils/localStorage';
const STORAGE_VIDEOS_DATA_KEY = 'VIDEOS_DATA';
class VideoItem extends Component {
constructor(props) {
super(props);
this.state = {
playingStatus: false,
videoId: 318298217,
};
}
componentDidMount() {
window.addEventListener(
'beforeunload',
this.saveStateToLocalStorage
);
}
componentWillUnmount() {
window.removeEventListener(
'beforeunload',
this.saveStateToLocalStorage
);
this.saveStateToLocalStorage();
}
handlePlayingStatus = () => {
this.seekToPoint();
this.setState({
playingStatus: true,
});
}
setVideoProgress = videoProgress => {
this.setState({
videoProgress: videoProgress.playedSeconds,
});
}
onVideoPause = () => {
this.saveStateToLocalStorage();
this.setState({
playingStatus: false,
});
}
onVideoEnd = () => {
console.log('backend call - video end status');
}
seekToPoint = () => {
const { videoId } = this.state;
const videosData = storage.hasKey(STORAGE_VIDEOS_DATA_KEY) &&
JSON.parse(storage.getItem(STORAGE_VIDEOS_DATA_KEY));
const toReturnVideoPoint = videosData[videoId] || 0;
this.player.seekTo(Number(toReturnVideoPoint));
}
saveStateToLocalStorage = () => {
const { videoProgress, videoId } = this.state;
const videosPlayedDuration = {
[videoId]: videoProgress,
};
storage.setItem(STORAGE_VIDEOS_DATA_KEY, JSON.stringify(videosPlayedDuration));
};
render() {
const { playingStatus, videoId } = this.state;
return (
<Fragment>
<ReactPlayer
ref={player => { this.player = player; }}
playing={playingStatus}
url={`https://player.vimeo.com/video/${videoId}`}
onPause={this.onVideoPause}
onEnded={this.onVideoEnd}
onProgress={this.setVideoProgress}
/>
<button onClick={this.handlePlayingStatus}>GO BACK TO THE PREVIOUS POINT</button>
</Fragment>
);
}
}
export default VideoItem;
As you can see it is a class component. I'm trying to remodel it in order to achieve less code with functional component with hooks. I tried that but what is happening here in ComponentDidMount was repeated too many times.
How can I stop too many componentDidMount logic rerenders in useEffect hook?
Upvotes: 0
Views: 36
Reputation: 11725
Pass an empty array as a parameter, eg:
useEffect(() => {
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage();
};
}, []);
When you use useEffect
, it's similar as using componentDidMount
, componentDidUpdate
and componentWillUnmount
in the same hook. The body of your function is what runs when your component is mounted, and on every update it receives. The return function is what runs before your component unmounts.
You can pass a second optional parameter, an array of values, to tell React to only run the function again when some variables between renders have changed. When you pass an empty array, you're just telling React to never update it at all.
Check the React Hooks documentation to learn more about that.
Upvotes: 1