Javascript React不会呈现递归反应组件

Javascript React不会呈现递归反应组件,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,鉴于这一组成部分: import React, { Component } from 'react'; import TrackerReact from 'meteor/ultimatejs:tracker-react'; export default class SubscriptionView extends TrackerReact(Component) { constructor(props) { super(props); let params = props

鉴于这一组成部分:

import React, { Component } from 'react';
import TrackerReact from 'meteor/ultimatejs:tracker-react';

export default class SubscriptionView extends TrackerReact(Component) {

  constructor(props) {
    super(props);

    let params = props.params || [];

    if (!Array.isArray(params)) {
      params = [params];
    }

    this.state = {
      subscription: {
        collection: Meteor.subscribe(props.subscription, ...params)
      }
    };
  }

  componentWillUnmount() {
    this.state.subscription.collection.stop();
  }


  render() {
    let loaded = this.state.subscription.collection.ready();

    if (!loaded) {
      return (
        <section className="subscription-view">
          <h3>Loading...</h3>
        </section>
      );
    }

    return (
      <section className="subscription-view">
        { this.props.children }
      </section>
    );
  }
};
就这样

在服务器端,两种发布方法都是

Meteor.publish('allFoo', function () {
  console.log("Subscribing foos");
  return Foos.find();
});

Meteor.publish('singleBar', function (id) {
  console.log("Subscribing bar", id);
  return Bars.find({ _id: id });
});
正在调用这两个发布方法

为什么第二个订阅视图不是被动的


*解决方案* 这是基于客户的评论:

import React, { Component } from 'react';
import TrackerReact from 'meteor/ultimatejs:tracker-react';

export default class SubscriptionLoader extends TrackerReact(Component) {

  constructor(props) {
    super(props);

    let params = props.params || [];

    if (!Array.isArray(params)) {
      params = [params];
    }

    this.state = {
      done: false,
      subscription: {
        collection: Meteor.subscribe(props.subscription, ...params)
      }
    };
  }

  componentWillUnmount() {
    this.state.subscription.collection.stop();
  }

  componentDidUpdate() {
    if (!this.state.done) {
      this.setState({ done: true });

      this.props.onReady && this.props.onReady();
    }
  }


  render() {
    let loaded = this.state.subscription.collection.ready();

    if (!loaded) {
      return (
        <div>Loading...</div>
      );
    }

    return null;
  }
};
其中
setReady
仅设置组件的状态,而
content
只有在
this.state.barReady&&this.state.foosrady
为true时才具有值


它起作用了

尝试将
SubscriptionView
组件分离出来,如下所示:

import SubscriptionView from './SubscriptionView.jsx';

export const Foo = () => (
    <div>
      <SubscriptionView subscription="singleBar" params={ 123 }>
        <div>Rendered!</div>
      </SubscriptionView>
      <SubscriptionView subscription="allFoo">
        <div>Rendered Again!</div>
      </SubscriptionView>
    </div>
);
import SubscriptionView from./SubscriptionView.jsx';
导出常量Foo=()=>(
提供!
又来了!
);
编辑评论对话


我不确定我的思路是否正确,但您可以将Foo构建为一个“智能”组件,根据需要将道具传递给每个SubscriptionView,然后将Foo用作可重用组件

假设我需要呈现的是FooBarForm,它要求在特定用例中同时注册Foos和bar。你会怎么做

您可以创建组件
Foos
bar
,根据需要使用道具,并创建包含这些组件并传递必要数据的父组件
FooBarForm

FooBarForm
将处理状态,并在状态发生变化时将其传递给其子组件的props

现在,状态由父组件集中管理,子组件使用从父组件传递的道具进行渲染


子组件将在其道具更改时重新渲染,具体取决于从父组件传递的状态是否已更改

这个例子很简单,但是实际的应用程序需要太多的集合才可用。我只是想为它编写一个通用组件,然后重用它。当子对象(例如:表单)实际呈现时,所有集合都将准备就绪,所有数据都将可用。由于应用程序将有许多这样的要求,有时是一个、两个或三个订阅,我希望充分利用React的可重用性。不确定我是否走上了正确的轨道,但你可以将Foo构建为一个“智能”组件,根据需要将道具传递给每个SubscriptionView,然后将Foo作为可重用组件使用。我不明白你的建议。。。假设我需要呈现的是
FooBarForm
,它要求在特定用例中注册
Foos
bar
。您将如何做到这一点?您可以创建组件Foos和bar,这些组件根据需要使用道具,并创建包含这些组件并传递必要数据的父组件FooBarForm。FooBarForm将处理状态,并在状态发生变化时将其传递给其子组件的道具。现在,状态由父组件和子组件渲染道具集中管理。子组件将在其道具更改时重新渲染,具体取决于从父组件传递的状态是否已更改。
import React, { Component } from 'react';
import TrackerReact from 'meteor/ultimatejs:tracker-react';

export default class SubscriptionLoader extends TrackerReact(Component) {

  constructor(props) {
    super(props);

    let params = props.params || [];

    if (!Array.isArray(params)) {
      params = [params];
    }

    this.state = {
      done: false,
      subscription: {
        collection: Meteor.subscribe(props.subscription, ...params)
      }
    };
  }

  componentWillUnmount() {
    this.state.subscription.collection.stop();
  }

  componentDidUpdate() {
    if (!this.state.done) {
      this.setState({ done: true });

      this.props.onReady && this.props.onReady();
    }
  }


  render() {
    let loaded = this.state.subscription.collection.ready();

    if (!loaded) {
      return (
        <div>Loading...</div>
      );
    }

    return null;
  }
};
<section className="inventory-item-view">
  <SubscriptionLoader subscription='singleBar' params={ this.props.id } onReady={ this.setReady.bind(this, 'barReady') } />
  <SubscriptionLoader subscription='allFoos' onReady={ this.setReady.bind(this, 'foosReady') } />
  { content }
</section>
import SubscriptionView from './SubscriptionView.jsx';

export const Foo = () => (
    <div>
      <SubscriptionView subscription="singleBar" params={ 123 }>
        <div>Rendered!</div>
      </SubscriptionView>
      <SubscriptionView subscription="allFoo">
        <div>Rendered Again!</div>
      </SubscriptionView>
    </div>
);