在 Reactjs 中使用远程数据获取 InitialState 的正确方法是什么?

What is the proper way to getInitialState with remote data in Reactjs?

已解决。代码没问题,问题是导入不当。

它很长 post(由于代码示例)。感谢您的耐心等待,非常感谢您的帮助!

我们在前端有一个 RoR 后端和 React,我们使用 alt 作为 flux 的实现。我们还使用 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')
    )
  }

首先,您遇到的第一个错误:

Uncaught TypeError: Cannot read property 'map' of undefined

是因为你的组件中的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 以 return 商店的当前状态,然后您可以在 render 方法中使用它。在 componentDidMount 中,它们监听来自该存储的更改事件,以便该存储中发生的任何来自您应用程序中任何位置的事件都将触发重新呈现。 componentWillUnmount 清理事件侦听器。不要忘记这一点非常重要,否则您的应用程序将泄漏内存!接下来是 onChange 方法(可以有任何名称,它不是内部 React 方法),当发生更改事件时,商店将调用该方法。这只是将组件的状态设置为商店状态。他们在这里再次调用 getInitialState 可能有点令人困惑,因为您没有获得初始状态,而是获得商店的当前状态。

这里的另一个重要注意事项是,此示例不会立即与 ES6/ES2015 classes 一起工作,因为 React 不再将方法自动绑定到组件的实例。所以作为 class 实现的例子看起来像这样:

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>
    );
  }
}

很抱歉浪费你的时间阅读它,但我想通了,麻烦的原因是我在导入时犯了愚蠢的错误。本质上,我导入了另一个名称为 needed 的商店。

所以,而不是 import FeatureCategoryStore from '../stores/FeatureTypeStore';

应该是import FeatureCategoryStore from '../stores/FeatureCategoryStore';