我正在开发一个项目,该项目将受益于能够从设备的 GPS 无线电获取用户的地理位置(纬度和经度)。
天真地向相关路线的加载器添加一些地理定位代码是行不通的,因为 Remix 正在服务器端渲染页面(这正是我想要的),显然,地理定位代码没有任何意义。 (即使服务器支持地理定位,我想要用户的位置而不是服务器的位置。)
我该如何实施?
到目前为止,我已经借用了这个答案来渲染客户端的内容。
从某种意义上说,这种方法是有效的,我的代码是在客户端执行的,但它仍然不太有效。实际上,页面会短暂显示“此浏览器不支持地理位置”,然后
<div>
消失。
一旦我确信我可以获取纬度/经度数据并将其显示在页面上,我认为触发以纬度/经度作为参数重新加载页面的东西应该不难,我可以这样做我的地理位置查找。
我不是 JavaScript 专家,所以请原谅任何新手错误或误解。
我写了这个组件:
const MyComponent = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
return <div>Geolocation is not supported by this browser</div>
}
function showPosition(position) {
return <div>Latitude { position.coords.latitude }, Longitude: { position.coords.longitude }</div>
}
}
然后我将其插入到页面中,如下所示:
<Suspense fallback={<div>Loading</div>}>
{ MyComponent() }
</Suspense>
这是一个示例,展示如何获取客户端地理位置并将其存储在服务器会话中。
https://stackblitz.com/edit/remix-run-remix-3mumcj?file=app%2Froutes%2F_index.tsx
// routes/_index.tsx
export async function loader({ request }: LoaderFunctionArgs) {
const session = await getSession(request.headers.get('cookie'));
return json({
latitude: session.get('latitude'),
longitude: session.get('longitude'),
});
}
export async function action({ request }: ActionFunctionArgs) {
const coords = await request.json();
const session = await getSession(request.headers.get('cookie'));
session.set('latitude', coords.latitude);
session.set('longitude', coords.longitude);
return json(
{ success: true },
{ headers: { 'set-cookie': await commitSession(session) } }
);
}
export default function Index() {
const { latitude, longitude } = useLoaderData<typeof loader>();
const fetcher = useFetcher();
useEffect(() => {
navigator.geolocation.getCurrentPosition((position) => {
let { latitude, longitude } = position.coords;
fetcher.submit(
{ latitude, longitude },
{ method: 'post', encType: 'application/json' }
);
});
}, [latitude, longitude]);
return (...)
}