2

I have React Component in componentDidMount fetch data from the server. The issue is componentDidMount called twice also the API called twice. I have a view increment API like youtube video views increment twice in the database because of twice API calling.

class SingleVideoPlay extends React.Component {
    constructor(props) {
        super(props);
        this.player = React.createRef();
    }
    state = {
        autoPlay: true,
        relatedVideos: [],
        video: null,
        user: null,
        comments: [],
        commentInput: {
            value: '',
            touch: false,
            error: false
        },
        following: false,
        tab: 'comments'
    };
    _Mounted = false;

    componentDidMount() {
        this._Mounted = true;
        if (this._Mounted) {
            const videoId = this.props.match.params.id;
            this.getVideoDetails(videoId);
        }
    }
    componentWillUnmount() {
        this._Mounted = false;
        try {
            clearInterval(this.state.videoInterval);
            this.props.videoEditUrl('');
        } catch (error) {}
    }
    captureVideoTime = async () => {
        const { video } = this.state;
        const result = await updateWatchTime({
            id: video._id,
            time: 1
        });
        if (result.status === 200) {
            const updateVideo = {
                ...video,
                secondsWatched: video.secondsWatched + 1
            };
            this.setState({ video: updateVideo });
        }
    };
    videoEnded = () => {
        clearInterval(this.state.videoInterval);
    };
    videoPause = () => {
        clearInterval(this.state.videoInterval);
    };
    loadVideo = () => {
        clearInterval(this.state.videoInterval);
    };
    playingVideo = () => {
        const interval = setInterval(this.captureVideoTime, 1000);
        this.setState({ videoInterval: interval });
    };
    
    getVideoDetails = async (videoId) => {
        const video = await getVideo(videoId);

        if (video.status === 200) {
            let response = video.data;
            if (this.props.userId)
                if (response.user._id === this.props.userId._id)
                    this.props.videoEditUrl(`/video/edit/${response.media._id}`);
            this.setState({
                relatedVideos: response.videos.docs,
                video: response.media,
                user: response.user
            });
            this.checkIsFollowing();
            this.updateVideoStat(response.media._id);
        }
    };
    updateVideoStat = async (id) => videoView(id);
    checkIsFollowing = async () => {
        const { userId } = this.props;
        const { video } = this.state;
        if (userId && video) {
            const response = await isFollow({
                follower: userId._id,
                following: video._id
            });
            if (response) {
                this.setState({ following: response.following });
            }
        }
    };
    addOrRemoveFollowing = async () => {
        this.checkIsFollowing();
        const { following, video } = this.state;
        const { userId } = this.props;
        if (userId) {
            if (following) {
                const response = await removeFollow({
                    follower: userId._id,
                    following: video._id
                });
                this.setState({ following: false });
            } else {
                const response = await addFollow({
                    follower: userId._id,
                    following: video._id
                });
                this.setState({ following: true });
            }
        }
    };

    submitCommentHandler = async (event) => {
        const { userId } = this.props;
        event.preventDefault();
        if (userId) {
            const result = await saveComment({
                mediaId: this.state.video._id,
                parentId: '0',
                userID: userId._id,
                userName: userId.username,
                comment: this.state.commentInput.value
            });
            console.log(result);
            if (result.status === 200) {
                this.getVideoComments();
                this.setState({ commentInput: { value: '', touch: false, error: false } });
            }
        }
    };

    render() {
        const { autoPlay, relatedVideos, video, user, comments, commentInput, following, tab } = this.state;
        const { userId } = this.props;
        return (
            <div className="container-fluid">
        
            some coponents
            </div>
        );
    }
}

const mapStateToProps = (state) => ({
    userId: state.auth.user
});

export default connect(mapStateToProps, { videoEditUrl })(SingleVideoPlay);

I don't know why componentDidMount called two times alse it shows memmory lecage issue.

How to Fix it.

Rohail Butt
  • 142
  • 1
  • 18
  • I would recommend you to place the component state within the constructor, like this: `this.state = {...}` – assembler Aug 12 '20 at 19:31

3 Answers3

4

Multiple componentDidMount calls can be caused by using <React.StrictMode>. After removing it double calls are gone.

This is intended behaviour, you can read more about it in the docs. It happens only development environment, while in production componentDidMount is called only once even with <React.StrictMode>.

This was tested with React 18.1.0

ImSpeakEnglish
  • 149
  • 3
  • 12
  • ok, thanks, what happens if i don't use stricmode? – Ali Alizadeh May 31 '22 at 06:12
  • 1
    Strict mode only adds some warnings to help with development. Those checks won't be performed anymore if you don't use strict mode. You can see more in the documentation: https://reactjs.org/docs/strict-mode.html – ImSpeakEnglish Jun 01 '22 at 07:30
0

I think the issue exists on the parent component that used SingleVideoPlay component. Probably that parent component caused SingleVideoPlay component rendered more than once. Also, there is an issue on your code.

    componentDidMount() {
        this._Mounted = true;
        if (this._Mounted) {
            const videoId = this.props.match.params.id;
            this.getVideoDetails(videoId);
        }
    }

Here, no need to check if this._Mounted, because it will always be true.

Hayden S.
  • 734
  • 4
  • 10
-2

1.Install jQuery by npm i jquery

  1. import $ from 'jquery'

  2. create your function or jwuery code after the export command or put at the end of the file

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 25 '22 at 11:12