I am a bit confused as to how to get this to work. I have three components - ReportsWrapper , ReportsNearby , and ReportSingle :
1.) ReportsWrapper gets the device location data then calls ReportsNearby passing the location as a prop
2.) ReportsNearby then uses that location to populate a "reports" collection from the mongodb
3.) Each record from "reports" is rendered via a ReportSingle component
Problem is that the "reports" collection does not populate the page at first load. The page loads, no data (data from mongodb) is shown on the client.
If I navigate to a different page (like /about or /settings) then back to ReportsWrapper, the collection seems to populate as expected and a ReportSingle is displayed for each record. Once I refresh on ReportsWrapper the collection is once again empty.
Any ideas?
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
});
});
I ended up getting this working by adding the following code to ReportsWrapper.jsx . I think that ReportsNearby was not getting the latLng prop as expected, even though I had console logged it to verify.
tl;dr Use a timer interval to make sure your app has received the location.
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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.