我的渲染方法中有以下代码:
render() {
return (
<div>
{this.props.spatulaReady.ready() ? <p>{this.props.spatula.name}</p> : <p>loading spatula</p>}
</div>
)
}
根据我的理解,检查订阅处理是否准备就绪(数据是否存在)并显示它。如果没有可用数据,则应显示简单的加载消息。但是,当我第一次加载页面时,此代码段已打开,它会卡在加载部分上。在页面重新加载数据(通常)显示正常。
如果我在页面首次加载时检查spatulaReady.ready()并且当显示器卡在“加载刮刀”和应该存在的数据时,则句柄报告为就绪并且数据是不是应该是这样的。如果我刷新页面,它也显示正常。问题是,这种检查数据和呈现的方式(如果它已经到达)在过去对我来说很好。是因为渲染方法不是被动的吗?因为handle.ready()应该是被动的。
甚至更奇怪的是它有时会在页面加载时正确地显示数据,看似随意。
CreateContainer代码:
export default createContainer(props => {
return {
user: Meteor.user(),
spatulaReady: Meteor.subscribe('spatula.byId', props.deviceId),
spatula: SpatulaCollection.findOne()
}
}, SpatulaConfig)
出版物代码:
Meteor.publish('spatula.byId', function(deviceId) {
const ERROR_MESSAGE = 'Error while obtaining spatula by id'
if (!this.userId) //Check for login
throw new Meteor.Error('Subscription denied!')
const spatula = SpatulaCollection.findOne({_id: deviceId})
if(!spatula) //No spatula by this id
throw new Meteor.Error(403, ERROR_MESSAGE)
if(spatula.ownedBy != this.userId) //Spatula does not belong to this user
throw new Meteor.Error(403, ERROR_MESSAGE)
return SpatulaCollection.find({_id: deviceId})
})
我知道我在这里错过了一块拼图,但我找不到它是不成功的。如果你不知道我的具体问题的解决方案,那么在展示它之前用另一种等待数据到达的方式指向我正确的方向也非常感谢。
编辑:在做了一些反复试验并阅读了与我的项目有关的其他各种帖子后,我找到了解决方案:
export default createContainer(props => {
const sHandle= Meteor.subscribe('spatula.byId', props.deviceId)
return {
user: Meteor.user(),
spatulaReady: sHandle.ready(),
spatula: SpatulaCollection.findOne()
}
}, SpatulaConfig)
对我来说,移动ready()调用创建容器修复了我所有的问题仍然没有意义。
答案 0 :(得分:2)
正如您所知,将.ready()
电话移至createContainer
可解决问题。这是因为Meteor反应性仅在您调用反应式数据源(反应函数)时起作用,例如反应式上下文中的collection.find()
或subscriptionHandle.ready()
,例如Tracker.autorun
或createContainer
。 React组件中的函数(包括render
)从Meteor的角度来看是非反应性上下文。
请注意,React和Meteor反应性是两回事。 React的反应性很简单,只要组件的props
或state
发生变化,它的render
功能就会重新运行。它对Meteor的反应数据源一无所知。由于createContainer
(当其中的反应数据源发生变化时由 Meteor 反应重新运行)只是将道具传递给底层组件,因此当道具给出时,React会重新呈现该组件来自createContainer
更改。