javascript - 为什么 Meteor 集合没有在第一次 render() 时填充?

标签 javascript mongodb meteor reactjs components

我对如何让它发挥作用有点困惑。我有三个组件 - ReportsWrapperReportsNearbyReportSingle:

1.) ReportsWrapper 获取设备位置数据,然后调用 ReportsNearby 将位置作为 prop 传递

2.) ReportsNearby 然后使用该位置从 mongodb 填充“报告”集合

3.) “reports”中的每条记录均通过 ReportSingle 组件呈现

问题是“报告”集合在首次加载时不会填充页面。页面加载,客户端上没有显示任何数据(来自 mongodb 的数据)。

如果我导航到不同的页面(例如/about 或/settings),然后返回 ReportsWrapper,该集合似乎会按预期填充,并且会为每条记录显示一个 ReportSingle。当我刷新 ReportsWrapper 后,集合再次为空。

有什么想法吗?

ReportsWrapper.jsx

import React, {Component} from "react";
import TrackerReact from "meteor/ultimatejs:tracker-react";    
import ReportsNearby from "./ReportsNearby.jsx";

export default class ReportsWrapper extends TrackerReact(Component) {                
    render() {    
        if (Geolocation.latLng() == null) {
            return (
                <span>Determining location...</span>
            )
        }

        return (
            <div>
                <h1>Reports</h1>
                <ReportsNearby latLng={Geolocation.latLng()} />
            </div>
        )
    }
}

ReportsNearby.jsx

import React, {Component} from "react";
import TrackerReact from "meteor/ultimatejs:tracker-react";
import ReportSingle from "./ReportSingle.jsx";
import NearbyMap from "../maps/NearbyMap.jsx"

export default class ReportsNearby extends TrackerReact(Component) {    
    constructor(props) {
        super(props);
        this.state = {
            subscription: {
                reports: Meteor.subscribe("nearbyReports", 5, props.latLng)
            }
        }
    }

    componentWillUnmount() {
        this.state.subscription.reports.stop();
    }

    _reports() {
        return Reports.find().fetch();
    }

    render() {
        console.log(this._reports()); // this is empty - why???
        return (
            <div>
                <ul>
                    {this._reports().map((report, index)=> {
                        return <ReportSingle key={report._id}
                                             report={report}
                    })}
                </ul>
            </div>
        )
    }
}

ReportSingle.jsx

import React, {Component} from 'react';

export default class ReportSingle extends Component {        
    render() {    
        return (
            <li>
                <a href={`/report/${this.props.report._id}`}>
                    {this.props.report.category}<br/>
                    {this.props.report.description}<br/>
                    {this.props.report.status}
                </a>
            </li>
        )
    }
}

routes.jsx

import React from "react";
import {mount} from "react-mounter";
import {MainLayout} from "./layouts/MainLayout.jsx";
import ReportsWrapper from "./reports/ReportsWrapper.jsx";
import Settings from "./Settings.jsx";
import About from "./About.jsx";

FlowRouter.route('/', {
    action() {
        mount(MainLayout, {
            content: <ReportsWrapper />
        })
    }
});

FlowRouter.route('/settings', {
    action() {
        mount(MainLayout, {
            content: <Settings />
        })
    }
});

FlowRouter.route('/about', {
    action() {
        mount(MainLayout, {
            content: <About />
        })
    }
});

publish.jsx

Meteor.publish("nearbyReports", function (limit, latLng) {
    Reports._ensureIndex({'lngLat': '2dsphere'});
    return Reports.find({
        lngLat: {
            $near: {
                $geometry: {
                    type: "Point",
                    coordinates: [latLng.lng, latLng.lat]
                },
                $minDistance: 0,
                $maxDistance: 3218.69 // this is 2 miles in meters
            }
        }
    }, {
        sort: {createdAt: -1},
        limit: limit,
        skip: 0
    });
});

最佳答案

我最终通过将以下代码添加到 ReportsWrapper.jsx 来实现此功能。我认为 ReportsNearby 没有按预期获得 latLng 属性,即使我有控制台记录它来验证。

tl;dr 使用计时器间隔来确保您的应用已收到位置信息。

constructor () {
    super();
    this.state = {
        handle: null,
        latLng: Geolocation.latLng()
    }
}

componentDidMount() {
    if (this.state.latLng != null) {
        return
    }

    // Attempt to reload the location if it was not found. do this because the device 
    // location is not immediately available on app start
    this.state.handle = Meteor.setInterval(()=> {
        if (Geolocation.latLng() != null) {
            this.setState({latLng: Geolocation.latLng()}); // Setting the state will trigger a re-render
            Meteor.clearInterval(this.state.handle); // Stop the interval function
        }
    }, 500)
}

componentWillUnmount() {
    // Make sure interval is stopped
    Meteor.clearInterval(this.state.handle);
}

关于javascript - 为什么 Meteor 集合没有在第一次 render() 时填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37015830/

相关文章:

javascript - 表单重置后调用函数

javascript - mvc dropdownlist - 在不附加事件处理程序的情况下捕获更改事件

MongoDB 获取按计数排序的文档

javascript - 在 MongoDB 中获取查询外的数据

mongodb - 没有重复的 Mongoose 数组推送

javascript - 在 React (v0.14.8) 中加载 Meteor (v1.3) 数据的首选方式

javascript - 在 Meteor.js 中设置自动表单中省略字段的值

javascript - 使用 JavaScript 中的 RegExp 删除重复的逗号和开头/结尾处的多余逗号,并删除重复的数字?

javascript - 如何拆分 0 天 15 小时 1 分钟 0 秒并将其分配到 java 脚本中的不同变量中?

javascript - JWPLAYER:加载播放器时出错:找不到可播放的源(Meteor)