ReactJs пытается подключить обработчик onclick до того, как Ajax загрузит элемент

0

Я создаю динамический список для меню в ReactJs. Данные для каждого пункта меню выбиваются из файла JSON через AJAX. Я хочу, чтобы меню закрывалось при нажатии элемента меню. Я перечисляю весь список пропеллера "whenClicked" при нажатии на один из пунктов меню. Ниже приведен код:

var MenuList = React.createClass({
    getInitialState: function() {
        return {data: []}
    },
    componentWillMount: function() {
        $.ajax({
            url: 'http://10.0.0.97:8888/public-code/data/data.json',
            dataType: 'json',
            success: function(data) {
                this.setState({data: data});
            }.bind(this),
            error: function(xhr, status, error) {
                var err = JSON.parse(xhr.responseText);
                console.log(err.Message);
            }
        });
    },
    render: function() {
        var list = this.state.data.map(function(menuItemProps) {
            return <MenuItem onClick={this.props.whenClicked} {...menuItemProps} key={menuItemProps.id} />
        });
        return (
            <ul id="menu-list">
                {list}
            </ul>
        )
    }
});

Затем "whenClicked" поддерживает функцию в родительском меню "handleClick", которая изменяет состояние меню и закрывает его, если он открыт. Вот код для компонента родительского меню, который содержит компонент MenuList выше:

module.exports = React.createClass({

    getInitialState: function() {
        return {open: false, mobi: false}
    },
    handleClick: function() {
        this.setState({open: !this.state.open})
    },
    closeOnMobiScroll: function() {
        /*
        if(this.state.mobi === false) {
            this.setState({open: false})
        }
        */
    },
    updateDimensions: function() {
        $(window).width() >= 767 ? this.setState({mobi: true}) : this.setState({mobi: false});
    },
    componentWillMount: function() {
        this.updateDimensions();
    },
    componentDidMount: function() {
        $(window).on("resize", this.updateDimensions);
    },
    componentWillUnmount: function() {
        $(window).on("resize", this.updateDimensions);
    },
    render: function() {
        return (

            <div id="menu" className={(this.state.open ? 'open' : '')} >
                <div id="menu-inner-wrap">
                    <MenuTitle />
                    <MenuToggle whenClicked={this.handleClick}/>
                    <MenuList whenClicked={this.handleClick}/>
                </div>
            </div>

        )
    }

});

Проблема заключается в том, что весь сценарий прерывается перед вызовом AJAX, и я получаю следующую ошибку:

Uncaught TypeError: Cannot read property 'whenClicked' of undefined

Поскольку я не вижу свое сообщение об ошибке AJAX в консоли, я подозреваю, что проблема в том, что React пытается подключить

onClick={this.props.whenClicked}

перед загрузкой моих данных.

Есть ли способ решить это? Есть ли что-то еще, что мне не хватает?

Теги:

2 ответа

1
Лучший ответ

Проблема не имеет ничего общего с вызовом Ajax или с React.

Внутри обратного вызова вы переходите к .map, this относится к глобальному объекту, а не к компоненту. Глобальный объект не имеет свойства prop, следовательно, ошибки.

Вы можете использовать .bind для привязки this значения функции к компоненту:

this.state.data.map(function(...) { ... }.bind(this));

Дополнительная информация: Как получить доступ к правильному "этому" контексту внутри обратного вызова?

  • 0
    Конечно же, это сработало. Спасибо за просвещение и ссылку.
1

Похоже, вам нужно привязать надлежащий контекст для функции сопоставления. Пытаться:

var list = this.state.data.map( function(menuItemProps) {
    return <MenuItem onClick={this.props.whenClicked} {...menuItemProps} key={menuItemProps.id} />
}.bind(this) );

Ещё вопросы

Сообщество Overcoder
Наверх
Меню