gpt4 book ai didi

javascript - React 不渲染递归 react 组件

转载 作者:行者123 更新时间:2023-11-30 15:53:34 25 4
gpt4 key购买 nike

给定这个组件:

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 在数据可用时重新呈现,但是第二个只呈现一次,仅此而已。如果我在 SubscriptionView 的渲染函数中放置一个 console.log(this.props.subscription, ready);,我会看到

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 时才有值是真的。

有效!

最佳答案

尝试像这样分离您的 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 构建为“智能”组件,根据需要将 Prop 传递给每个 SubscriptionView,然后将 Foo 用作可重用组件。

Let's say that what I need to render is FooBarForm, which requires both Foos and Bars to be registered, in that specific use case. How would you do that?

您可以创建组件 FoosBars 根据需要获取 props 并创建父组件 FooBarForm 包含这些组件并传递必要的数据。

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

现在 state 由父组件集中管理,子组件使用从父组件传递的 props 进行渲染。

子组件将根据从父组件传递的状态是否已更改,在它们的 props 更改时重新渲染。

关于javascript - React 不渲染递归 react 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38928525/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com