Как правильно получить метод getInitialState с удаленными данными в Reactjs?
ЭТО РЕШЕНО. Код был в порядке, проблема была с неправильным импортом.
Это длинный пост (из-за примеров кода). Буду признателен за ваше терпение и буду очень благодарен за вашу помощь!
У нас есть серверная часть RoR и React на внешней стороне, и мы используем alt в качестве реализации потока. Мы также используем babel для компиляции ES6 в ES5. Так что проблема в том, что я не могу сделать компонент из-за 2 ошибок.
Во-первых Uncaught TypeError: Cannot read property 'map' of undefined
Он появляется в функции рендеринга компонента MapPalette:
render() {
return (
<div>
{this.state.featureCategories.map(fc => <PaletteItemsList featureCategory={fc} />)}
</div>
);
}
И второе Uncaught Error: Invariant Violation: receiveComponent(...): Can only update a mounted component.
Так вот весь компонент MapPalette
"use strict";
import React from 'react';
import PaletteItemsList from './PaletteItemsList';
import FeatureCategoryStore from '../stores/FeatureTypeStore';
function getAppState() {
return {
featureCategories: FeatureCategoryStore.getState().featureCategories
};
}
var MapPalette = React.createClass({
displayName: 'MapPalette',
propTypes: {
featureSetId: React.PropTypes.number.isRequired
},
getInitialState() {
return getAppState();
},
componentDidMount() {
FeatureCategoryStore.listen(this._onChange);
},
componentWillUnmount() {
FeatureCategoryStore.unlisten(this._onChange);
},
render() {
return (
<div>
{this.state.featureCategories.map(fc => <PaletteItemsList featureCategory={fc} />)}
</div>
);
},
_onChange() {
this.setState(getAppState());
}
});
module.exports = MapPalette;
FeatureCategoryStore
var featureCategoryStore = alt.createStore(class FeatureCategoryStore {
constructor() {
this.bindActions(FeatureCategoryActions)
this.featureCategories = [];
}
onReceiveAll(featureCategories) {
this.featureCategories = featureCategories;
}
})
module.exports = featureCategoryStore
FeatureCategoryActions
class FeatureCategoryActions {
receiveAll(featureCategories) {
this.dispatch(featureCategories)
}
getFeatureSetCategories(featureSetId) {
var url = '/feature_categories/nested_feature_types.json';
var actions = this.actions;
this.dispatch();
request.get(url)
.query({ feature_set_id: featureSetId })
.end( function(response) {
actions.receiveAll(response.body);
});
}
}
module.exports = alt.createActions(FeatureCategoryActions);
И последнее - как я отрисовываю компонент React.
var render = function() {
FeatureCategoryActions.getFeatureSetCategories(#{ @feature_set.id });
React.render(
React.createElement(FeatureSetEditMap, {featureSetId: #{@feature_set.id}}),
document.getElementById('react-app')
)
}
2 ответа
Извините, что вы потратили время на чтение, но я понял это, и причиной проблемы была моя глупая ошибка при импорте. По сути, я импортировал еще один магазин с именем нужного.
Итак, вместо import FeatureCategoryStore from '../stores/FeatureTypeStore';
Так должно быть import FeatureCategoryStore from '../stores/FeatureCategoryStore';
Прежде всего, первая ошибка, которую вы получите:
Uncaught TypeError: Невозможно прочитать свойство 'map' из неопределенного
Это потому что this.state
в вашем компоненте не определено, что означает, что вы, вероятно, не реализовали getInitialState
в вашем компоненте.
Вы не включили полную реализацию вашего компонента, которую мы должны увидеть, чтобы иметь возможность помочь вам. Но давайте пройдемся по их примеру компонента представления:
var LocationComponent = React.createClass({
getInitialState() {
return locationStore.getState()
},
componentDidMount() {
locationStore.listen(this.onChange)
},
componentWillUnmount() {
locationStore.unlisten(this.onChange)
},
onChange() {
this.setState(this.getInitialState())
},
render() {
return (
<div>
<p>
City {this.state.city}
</p>
<p>
Country {this.state.country}
</p>
</div>
)
}
})
Они реализуют getInitialState
здесь, чтобы вернуть текущее состояние магазина, который вы затем сможете использовать в render
метод. В componentDidMount
они прослушивают изменения событий из этого хранилища, так что любые события, происходящие в этом хранилище, поступающие из любого места в вашем приложении, будут вызывать повторную визуализацию. componentWillUnmount
убирает слушателя события. Очень важно не забыть об этом, иначе ваше приложение будет пропускать память! Далее onChange
метод (который может иметь любое имя, это не внутренний метод React), который магазин будет вызывать при возникновении события изменения. Это просто устанавливает состояние компонента в любое состояние хранилища. Может быть немного сбивает с толку, что они называют getInitialState
опять же, потому что вы не получаете начальное состояние, вы получаете текущее состояние магазина.
Еще одно важное замечание: этот пример не будет работать с классами ES6/ES2015, потому что React больше не привязывает методы автоматически к экземпляру компонента. Таким образом, пример, реализованный как класс, будет выглядеть примерно так:
class LocationComponent extends React.Component {
constructor(props) {
super(props)
this.state = this.getState();
this.onChangeListener = () => this.setState(this.getState());
}
getState() {
return locationStore.getState();
}
componentDidMount() {
locationStore.listen(this.onChangeListener);
}
componentWillUnmount() {
locationStore.unlisten(this.onChangeListener)
}
render() {
return (
<div>
<p>
City {this.state.city}
</p>
<p>
Country {this.state.country}
</p>
</div>
);
}
}