[英]React does not render recursive reactive components
鑒於此組件:
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
被重新渲染,但是第二個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
僅設置組件的狀態,並且僅當this.state.barReady && this.state.foosReady
為true時, content
才具有值。
有用!
嘗試像這樣分離出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構建為“智能”組件,並根據需要將道具傳遞給每個SubscriptionView,然后將Foo用作可重用組件。
假設我需要渲染的是FooBarForm,它需要在該特定用例中同時注冊Foos和Bars。 你會怎么做?
您可以創建按需使用道具的Components Foos
和Bars
,並創建一個包含這些Components並傳遞必要數據的父組件FooBarForm
。
FooBarForm
將處理狀態,並且隨着狀態的改變將其傳遞給其子組件的props。
現在狀態由父組件集中管理,子組件使用從父組件傳遞的道具進行渲染。
根據從父組件傳遞的狀態是否已更改,子組件將隨着其道具的更改而重新呈現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.