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