鉴于此组件:
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>
);
}
};
另一个组成部分:
import SubscriptionView from './SubscriptionView.jsx';
export const Foo = () => (
<SubscriptionView subscription="allFoo">
<SubscriptionView subscription="singleBar" params={ 123 }>
<div>Rendered!</div>
</SubscriptionView>
</SubscriptionView>
);
当数据可用时,第一个Subscription
会被重新渲染,但第二个只渲染一次而不再渲染。如果我在console.log(this.props.subscription, ready);
的渲染函数中放置SubscriptionView
,我会看到
allFoo false
allFoo true
singleBar false
就是这样。
在服务器端,两种发布方法都是
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 });
});
正在调用这两种发布方法。
为什么不是第二个SubscriptionView
被动?
这是基于alexi2的评论:
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;
}
};
然后,在父组件的render
方法中:
<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>
setReady
仅设置组件的状态,content
仅在this.state.barReady && this.state.foosReady
为真时才有值。
有效!
答案 0 :(得分:2)
尝试将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>
);
根据评论对话进行修改
不确定我是否在正确的轨道上但您可以将Foo构建为“智能”组件,根据需要将props传递给每个SubscriptionView,然后使用Foo作为可重用组件。
让我们说我需要呈现的是FooBarForm,它需要在特定用例中注册Foos和Bars。你会怎么做?
您可以创建根据需要获取道具的组件Foos
和Bars
,并创建包含这些组件并传递必要数据的父组件FooBarForm
。
FooBarForm
将处理状态,并且当更改时将其传递给其子组件的props。
现在,状态由父组件集中管理,子组件使用从父组件传递的props进行渲染。
子组件会在其道具发生变化时重新渲染,具体取决于从父组件传递的状态是否已更改。