gpt4 book ai didi

javascript - 在 withTracker 中使用 ReactiveVar 和 Meteor.call 避免无限循环?

转载 作者:行者123 更新时间:2023-11-30 06:23:56 26 4
gpt4 key购买 nike

目前我正在尝试使用功能性无状态组件,因为它们似乎更容易测试/模拟/保持故事书的独立性。

我已经开始使用 withTracker 以便将 React 组件与 Meteor 集成,并且在使用 Meteor.subscribe 时一切正常,例如:

...
module.exports = withTracker( (props) => {
subscription = Meteor.subscribe( 'posts' )

loading = subscription.ready()
posts = Posts.find({}).fetch()

return {loading, posts}
} )( LowerLevelComponent )
...

但有时我需要让它成为 Reactive 但使用 Meteor.call,例如:

...
module.exports = withTracker( (props) => {
feed = new ReactiveVar(null)

Meteor.call( 'feed', (error, response) => {

work = // do some work

feed.set( work )
} )

loading = subscription.ready()
feed = feed.get()

return {loading, feed}
} )( LowerLevelComponent )
...

这里的问题是,每次该组件运行时,变量“feed”都会再次分配给 ReactiveVar,并且会再次调用 Meteor.call 并开始无限循环。


我找到的唯一解决方案是使用“feed”作为功能组件之外的 ReactiveVar,例如:

feed = new ReactiveVar(null)
module.exports = withTracker( (props) => {

if( feed.get() == null ) {
Meteor.call( 'feed', (error, response) => {

work = // do some work

feed.set( work )
} )
}

loading = subscription.ready()
feed = feed.get()

return {loading, feed}
} )( LowerLevelComponent )

这里出现的问题是:

  • 如果我在 Router 中导航然后返回此页面,ReactiveVar 是否仍会由该值填充,或者 withTracker 是否会确保它已从内存中销毁?

  • 如果我想要像这样的两个组件但加载不同的提要怎么办?我是否必须为范围外的变量使用“动态”名称?这看起来很老套。我看到一些人使用 Session 来存储这些东西,但这听起来更 hacky。

  • 理想情况下,我应该在哪里存储 ReactiveVar/Meteor.call 逻辑并使其仍然属于我的组件的特定实例?

  • 这就是“状态”的全部含义,我应该使用一些允许我设置状态的 React 组件吗?从我糟糕的 React 经验来看,最好永远不要使用状态,这样代码就可以在 StoryBook/Jest/任何需要使用的测试框架上轻松测试?

通过查看源码实现here我可以看到它将 this.props 和 this.data 发送到下层组件。这是 this.data 的把戏吗?这是我应该添加我的 ReactiveVar 的地方,以便我可以跟踪它并仍然保持它对那个实例是唯一的吗?


看完@Fred Stark 的回复:

So the main issue here is that by using a reactiveVar you are introducing state to the component. This makes functional stateless components a poor choice of pattern to represent what you're trying to do. Try using the class pattern with React.Component for this case

我得出的结论是,这里的主要问题不是我将状态引入组件,而实际上这里的主要问题是 Meteor.call 如何() 的行为方式与 Meteor.subscribe() 不同。

如果将“状态添加到函数无状态对象”是一个真正的问题,那么 withTracker 函数就没有意义了。 Meteor.subscribe() 确实将状态添加到 FSC,这是将 Meteor 数据与 React 集成的推荐方法之一,如 Meteor Guide 中所示

得出该结论后,我在网上进行了更多搜索,发现有一些实现试图解决这个问题,例如 meteor-callReactiveMethod .这些库 potential 将允许我以“包含”的方式隐藏解决方法,并使 Meteor.calls 的工作方式类似于 Meteor.subscribe()。

其他选择可能是不使用 Meteor.call 来获取数据,即使它不是 react 性的,但我不能 100% 确定这可能产生的副作用。

最佳答案

因此,经过几天的摸索,我终于找到了一个解决方案,它不会破坏我遵循的一些限制/规则,以便让我的组件兼容并在我的网站和故事书。

诀窍是创建一个不使用 withTracker 的包装函数,这个函数将在 react 性事件发生时持有这个“非 react 性”范围,所有这些都具有所有状态的优点一旦我的组件从屏幕上移除,就会“自动”创建和销毁(希望如此!!)。

代替:

feed = new ReactiveVar(null)
module.exports = withTracker( (props) => {

if( feed.get() == null ) {
Meteor.call( 'feed', (error, response) => {

work = // do some work

feed.set( work )
} )
}

loading = subscription.ready()
feed = feed.get()

return {loading, feed}
} )( LowerLevelComponent )

我现在在做:

module.exports = (props) => {

// NOTE: this will create a ReactiveVar everytime my HOC is created,
// without using withTracker.
feed = new ReactiveVar(null)

// The "reactive data" will live on my "Intermediary Order Object"
// which uses withTracker and will be reactive!
Intermediary = withTracker( (props) => {

if( feed.get() == null ) {
Meteor.call( 'feed', (error, response) => {

work = // do some work

feed.set( work )
} )
}

loading = subscription.ready()
feed = feed.get()

return {loading, feed}
} )( LowerLevelComponent )

<Intermediary {...props} />

关于javascript - 在 withTracker 中使用 ReactiveVar 和 Meteor.call 避免无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51604247/

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