为什么Meteor集合没有填充在第一个渲染()上?

时间:2016-05-03 23:05:04

标签: javascript mongodb meteor reactjs components

我对如何让它发挥作用感到有点困惑。我有三个组件 - ReportsWrapper ReportsNearby ReportSingle

1。) ReportsWrapper 获取设备位置数据,然后调用 ReportsNearby 将该位置作为道具传递

2。) ReportsNearby 然后使用该位置填充mongodb中的“报告”集合

3。)“报告”中的每条记录都是通过 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
    });
});

1 个答案:

答案 0 :(得分: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);
}