why componentdidmount called two times
Asked Answered
C

5

20

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.

Chariot answered 12/8, 2020 at 19:25 Comment(1)
I would recommend you to place the component state within the constructor, like this: this.state = {...}Solfatara
P
49

Multiple componentDidMount calls may be caused by using <React.StrictMode> around your component. After removing it double calls are gone.

This is intended behavior to help detect unexpected side effects. You can read more about it in the docs. It happens only in development environment, while in production componentDidMount is called only once even with <React.StrictMode>.

This was tested with React 18.1.0

Purificator answered 30/4, 2022 at 21:54 Comment(2)
ok, thanks, what happens if i don't use stricmode?Featherston
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: reactjs.org/docs/strict-mode.htmlPurificator
L
10

Strict mode runs your Component twice to ensure reusability. By removing React strictMode tag from index.js. this can be solved. you can find all behaviour of react strict mode in https://react.dev/reference/react/StrictMode

From:

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

To:

root.render(
  <App />
);
Labored answered 3/4, 2023 at 18:27 Comment(0)
N
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.

Neb answered 12/8, 2020 at 19:30 Comment(5)
why componentWillUnmount called after First Render component?Chariot
This means the parent component unmounts SingleVideoPlay component and mounts again.Neb
I'm using metronic theme but i can't understand this behaviour.linkChariot
Please post the calling Parent so we could see whats wrongObovate
The constructor is called multiple times.Mayhap
J
0

Change index.js from:

root.render( <React.StrictMode> </React.StrictMode> );

To:

root.render( <React.Fragment> </React.Fragment> );

This works for me.

Jerri answered 27/4 at 10:9 Comment(0)
C
-8

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

Calore answered 25/4, 2022 at 10:32 Comment(1)
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.Sarcomatosis

© 2022 - 2024 — McMap. All rights reserved.