D
D
Dmitry2019-04-30 18:17:15
React
Dmitry, 2019-04-30 18:17:15

Why doesn't jQuery find the element in componentDidMount()?

Hello, I am making an asynchronous request in componentDidMount but jQuery does not see the DOM tree element.

components/pages/VideotipsPage/VideotipsPage.jsx

import React, {Component} from 'react';
import Breadcrumbs from '../../../helpers/breadcrumbs';
import Preloader from '../../../helpers/preloader';
import {Route} from 'react-router-dom';
import ErrorPage from '../ErrorPage';
import videotipSinglePagePopupInit from './videotipSinglePageMagnificPopupInit';
import $ from 'jquery';



class VideotipSinglePage extends Component {
    constructor(props){
        super(props);
        this.state = {
            videotipSlug: this.props.match.params.videotip,
        };
    }

    componentDidMount() {
        const {setSingleVideotip} = this.props;
        const {videotipSlug} = this.state;
        setSingleVideotip(videotipSlug);

        this.$el = $('.movietiphome_single__inner');
        videotipSinglePagePopupInit(this.$el);
    }

    render(){

        console.log( 'this.$el inside of render', this.$el );

        const {videotipSingle: {title, video, image}, isVideotipSingleLoading, isVideotipSingleReady, videotipSingleError} = this.props;

        if (videotipSingleError === 404) {
            return <Route component={ErrorPage} />
        }

        if (isVideotipSingleLoading) {
            return <Preloader />
        }

        if (!isVideotipSingleReady) {
            return null;
        }

        return (
            <React.Fragment>
                <div className="container">
                    <div className="row">
                        <div className="col-xs-12">
                            <Breadcrumbs />
                        </div>
                    </div>
                </div>
                <div className="movietiphome_single">
                    <div className="container movietiphome_single__titleContainer">
                        <div className="row movietiphome_single__titleRow">
                            <div className="col-xs-12 movietiphome_single__titleCol">
                                <div className="movietiphome_single__title home__sectionTitle">
                                    {title}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="container movietiphome_single__container">
                    <div className="row movietiphome_single__row">
                        <div className="col-xs-12 movietiphome_single__col">
                            <div className="movietiphome_single__inner">
                                <div className="movietiphome_single__item">
                                    <a href={video} title={title} className="movietiphome_single__link">
                                        <img src={image} alt={title} className="movietiphome_single__img" />
                                        <span className="movietiphome_single__play"></span>
                                    </a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </React.Fragment>
        );
    }
}

export default VideotipSinglePage;

containers/pages/VideotipsPage/VideotipSinglePage.js

import {connect} from 'react-redux';
import VideotipSinglePage from '../../../components/pages/VideotipsPage/VideotipSinglePage';
import {setSingleVideotip} from '../../../actions/videotips';


const mapStateToProps = ({videotips: {videotipSingle, isVideotipSingleLoading, isVideotipSingleReady, videotipSingleError}}) => ({
    videotipSingle,
    isVideotipSingleLoading,
    isVideotipSingleReady,
    videotipSingleError
});

const mapDispatchToProps = dispatch => ({
    setSingleVideotip: slug => dispatch(setSingleVideotip(slug)),
});

export default connect(mapStateToProps, mapDispatchToProps)(VideotipSinglePage);

components/pages/VideotipsPage/videotipSinglePageMagnificPopupInit.js

export default function videotipSinglePagePopupInit($elem){
    console.log( '$elem inside function', $elem );

    $elem.each(function() {
        $(this).magnificPopup({
            type:'image',
            removalDelay: 500,
            mainClass: 'mfp-fade popup_inline',
            showCloseBtn: true,
            closeMarkup: '<div class="mfp-close">&times;</div>',
            closeBtnInside: true,
            closeOnContentClick: false,
            closeOnBgClick: true,
            alignTop: false,
            fixedContentPos: true,
            callbacks: {
                open: function() {
                    var headerHeight = $('.header__top').innerHeight();
                    $('.mfp-content').css({
                        'marginTop': headerHeight,
                    });

                    var mp = $.magnificPopup.instance,
                        t = $(mp.currItem.el[0]);

                    var $imgVideo = $(this.wrap[0]).find('img.mfp-img'),
                        $dataVideo = $(this.currItem.el).parent('.movietiphome_single__link').attr('href');

                    $imgVideo.addClass('has__video').attr('data-video', $dataVideo);

                    $imgVideo.parent('figure').append('<div class="movietiphome__play"></div>');
                    $('.mfp-content .movietiphome__play').click();
                },
                close: function() {

                },
                beforeOpen: function() {
                    var $triggerEl = $(this.st.el),
                        newClass = 'movietiphome__gallery';
                    this.st.mainClass = this.st.mainClass + ' ' + newClass;

                    this.st.image.markup = this.st.image.markup.replace('mfp-figure', 'mfp-figure mfp-with-anim');
                },
                elementParse: function(item) {
                    item.src = item.el.parent('.movietiphome_single__link').find('img').attr('src');
                },
                markupParse: function(template, values, item) {
                    values.title = item.el.parent('.movietiphome_single__link').attr('title');
                },
                change: function(){
                    var mp = $.magnificPopup.instance,
                        t = $(mp.currItem.el[0]);

                    var $imgVideo = $(this.wrap[0]).find('img.mfp-img'),
                        $dataVideo = $(this.currItem.el).attr('href');
                    $imgVideo.addClass('has__video').attr('data-video', $dataVideo);
                }
            },
            gallery: {
                enabled:false,
                navigateByImgClick: false,
            },
            delegate: '.movietiphome_single__play',
        });
    });
}

actions/videotips.js

import {
    SET_VIDEOTIPS,
    SET_VIDEOTIPS_SUCCEEDED,
    SET_VIDEOTIPS_FAILED,

    SET_VIDEOTIP_SINGLE,
    SET_VIDEOTIP_SINGLE_SUCCEEDED,
    SET_VIDEOTIP_SINGLE_FAILED,
} from '../actions/types/videotips-types';

export const setAllVideotips = () => {
    return async dispatch => {
        dispatch({type: SET_VIDEOTIPS});
        axios.get('/api/videotips').then(({data: videotips}) => {
            dispatch({type: SET_VIDEOTIPS_SUCCEEDED, payload: videotips});
        }).catch(err => {
            dispatch({type: SET_VIDEOTIPS_FAILED, payload: err});
        });
    };
};

export const setSingleVideotip = (slug) => {
    return async dispatch => {
        dispatch({type: SET_VIDEOTIP_SINGLE});
        axios.get(`/api/videotips/${slug}`).then(data => {
            const {videotip} = data.data;
            if (videotip) {
                dispatch({type: SET_VIDEOTIP_SINGLE_SUCCEEDED, payload: videotip});
            } else {
                dispatch({type: SET_VIDEOTIP_SINGLE_FAILED, payload: 404});
            }
        }).catch(err => {
            dispatch({type: SET_VIDEOTIP_SINGLE_FAILED, payload: 404});
        });
    };
};

I understand what I need to call
this.$el = $('.movietiphome_single__inner');
        videotipSinglePagePopupInit(this.$el);
after setSingleVideotip(videotipSlug);asynchronously, but I haven't figured out how to do it yet.
What do you think?
Thank you.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2019-04-30
@ddimonn8080

Why is jQuery not finding element in componentDidMount()

Because at the time of the call you show Preloader or null.
You shouldn't use jQuery in React development.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question