我一直在努力解决这个问题很长一段时间,但未能找到任何答案.
我使用react-meteor-data来管理我的数据,并在我的流星应用程序中做出反应.处理mongo的数据时工作正常,但我不能让它与道具反应.
在这里,在App.js,我打电话给我的容器,我想反应和重新呈现在应用变化的状态.
<MyContainer someState={this.state.MyState} />
Run Code Online (Sandbox Code Playgroud)
在MyContainer.js中,我有一个createContainer来自反应流星数据
export default createContainer(params => {
Meteor.subscribe('someCollection');
return {
someCollection: SomeCollection.find({}).fetch(),
stateFromParent: params.someState
};
}, MyContainer);
Run Code Online (Sandbox Code Playgroud)
这在第一次渲染组件时工作正常,MyContainer正确获取MyState.
事情是,当MyState从App改变时,我可以在Chrome Dev React工具中看到它确实已更新createContainer(ReactMeteorDataComponent具有正确更新状态的道具)但该createContainer功能未运行,因此props不更新MyContainer.
所以这些props是从谁更新,ReactMeteorDataComponent而不是MyContainer由谁无限期地保存数据.它就像createContainer不考虑其prop的更新有变化,因此不运行其功能.
我真的觉得我错过了一些东西,因为这似乎是非常基本的东西,谢谢你的帮助.
OP 没有提到状态是如何改变的,所以原来的例子是不完整的。因此,我将尝试解释容器创建的原理,希望对理解它有所帮助。
当其计算无效时(即,当反应性数据源之一,例如反应性变量、订阅句柄或获取的 MiniMongo 游标具有新值时),它使用 Meteor 的 Tracker 自动更新包装的组件。要了解有关 Tracker 的更多信息,请参阅Tracker 手册。这是一个深入的资源,不需要了解基础知识的工作原理。
它的执行方式与您通常在 Meteor 中进行反应性跟踪的方式不同,因为每当容器的 props 发生更改时,它也需要重新运行计算。
源代码不是很长或很复杂,可以在 GitHub 上找到(目前在这里)。
Tracker.autorun((c) => {
if (c.firstRun) {
//...
data = component.getMeteorData();
} else {
// Stop this computation instead of using the re-run.
// We use a brand-new autorun for each call to getMeteorData
// to capture dependencies on any reactive data sources that
// are accessed. The reason we can't use a single autorun
// for the lifetime of the component is that Tracker only
// re-runs autoruns at flush time, while we need to be able to
// re-call getMeteorData synchronously whenever we want, e.g.
// from componentWillUpdate.
c.stop();
// Calling forceUpdate() triggers componentWillUpdate which
// recalculates getMeteorData() and re-renders the component.
component.forceUpdate();
}
})
Run Code Online (Sandbox Code Playgroud)
每当计算无效(并因此重新运行)时,它就会停止计算并强制重新渲染容器,这将重新创建新的计算并具有更新的数据。
高级容器功能在这里(为简洁起见,删除了一些部分):
export const ReactMeteorData = {
componentWillMount() {
this.data = {};
this._meteorDataManager = new MeteorDataManager(this); // (1)
const newData = this._meteorDataManager.calculateData(); // (2)
this._meteorDataManager.updateData(newData); // (3)
},
componentWillUpdate(nextProps, nextState) {
// backup current state and props, assign next ones to components
let newData = this._meteorDataManager.calculateData(); // (2)
this._meteorDataManager.updateData(newData); // (3)
// restore backed up data
},
componentWillUnmount() {
this._meteorDataManager.dispose(); // (4)
},
};
Run Code Online (Sandbox Code Playgroud)
要点是: - 在安装之前,创建一个新的数据管理器(1)。它负责运行计算并this.data根据数据变化进行填充。- 首先,每当组件应该更新时,就会运行计算(2)并更新数据(3)。每当组件接收到新的状态或属性(在这种类型的容器中,它应该只是属性)时,就会发生更新,并且,正如我们之前所看到的,当 Tracker 计算由于调用component.forceUpdate().
包装的组件接收父级的 props,以及 Tracker 计算的数据,如下所示props:
return <WrappedComponent {...this.props} {...this.data} />;
Run Code Online (Sandbox Code Playgroud)
流星指南中有react-meteor-data一个简短的部分。
一般来说,指南中的简单示例(以及OP的示例)应该可以正常工作,只要使用(请参阅setState()上面的“它是如何工作的?”部分)适当设置状态即可。
此外,无需将容器状态重新映射到发送给子级的 props,因为它们会被传递(除非有充分的理由这样做)。
preventing re-renders如果您遇到任何性能问题,请考虑本节中的要点。
来自指南:
export default ListPageContainer = withTracker(({ id }) => {
const handle = Meteor.subscribe('todos.inList', id);
const loading = !handle.ready();
const list = Lists.findOne(id);
const listExists = !loading && !!list;
return {
loading,
list,
listExists,
todos: listExists ? list.todos().fetch() : [],
};
})(ListPage);
Run Code Online (Sandbox Code Playgroud)
在此示例中,请注意容器需要一个idprop,并且它也将可供包装组件以及loading、list等(来自示例中容器的计算)。
| 归档时间: |
|
| 查看次数: |
694 次 |
| 最近记录: |