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

时间:2015-04-22 23:21:27

标签: reactjs reactjs-flux flux react-alt

已经解决了。代码还可以,问题在于导入不当。

这是一篇很长的帖子(由于代码示例)。我将感谢您的耐心,非常感谢您的帮助!

我们在前端有一个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')
    )
  }

2 个答案:

答案 0 :(得分:2)

首先,你得到第一个错误:

  

未捕获的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>
    );
  }
}

答案 1 :(得分:0)

很抱歉你浪费时间阅读它,但我想出来了,麻烦的原因是我导入的愚蠢错误。基本上,我已经导入了另一个名为need的商店。

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

应为import FeatureCategoryStore from '../stores/FeatureCategoryStore';