React Integration Guide
Learn how to integrate route optimization and mapping into your React applications using @route-optimization/react.
Installation
bash
npm install @route-optimization/react @route-optimization/core
# or
pnpm add @route-optimization/react @route-optimization/core
# or
yarn add @route-optimization/react @route-optimization/coreCore Concepts
The React package provides hooks that wrap the core functionality with React-specific state management:
useRouteMap- Main hook for map rendering and route managementuseMapControls- Hook for map interaction controlsuseRouteOptimization- Hook for route calculation and optimizationuseOptimizationStatus- Hook for optimization progress tracking
Basic Map Rendering
Simple Route Map
tsx
import { useRouteMap } from '@route-optimization/react';
function RouteMapComponent() {
const { mapRef, renderRoute, clearRoute, isReady } = useRouteMap({
apiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
center: { lat: 13.7563, lng: 100.5018 }, // Bangkok
zoom: 12,
});
const handleShowRoute = () => {
renderRoute({
stops: [
{
id: '1',
location: { lat: 13.7563, lng: 100.5018 },
name: 'Start Location',
},
{
id: '2',
location: { lat: 13.7467, lng: 100.5352 },
name: 'End Location',
},
],
});
};
return (
<div>
<div ref={mapRef} style={{ width: '100%', height: '600px' }} />
<button onClick={handleShowRoute} disabled={!isReady}>
Show Route
</button>
<button onClick={clearRoute} disabled={!isReady}>
Clear Route
</button>
</div>
);
}Route Map View Component
For simpler usage, use the pre-built RouteMapView component:
tsx
import { RouteMapView } from '@route-optimization/react';
function App() {
const [route, setRoute] = useState(null);
return (
<RouteMapView
apiKey="YOUR_GOOGLE_MAPS_API_KEY"
route={route}
mapConfig={{
center: { lat: 13.7563, lng: 100.5018 },
zoom: 12,
}}
onError={(error) => console.error('Map error:', error)}
/>
);
}Map Controls
Using Map Controls Hook
tsx
import { useRouteMap, useMapControls } from '@route-optimization/react';
function InteractiveMap() {
const { mapRef, map, isReady } = useRouteMap({
apiKey: 'YOUR_API_KEY',
});
const { center, zoom, bounds, setCenter, setZoom, fitBounds } = useMapControls(map);
const handleCenterBangkok = () => {
setCenter({ lat: 13.7563, lng: 100.5018 });
};
const handleZoomIn = () => {
setZoom((zoom ?? 12) + 1);
};
return (
<div>
<div ref={mapRef} style={{ width: '100%', height: '600px' }} />
<div className="controls">
<p>
Center: {center?.lat.toFixed(4)}, {center?.lng.toFixed(4)}
</p>
<p>Zoom: {zoom}</p>
<button onClick={handleCenterBangkok}>Center on Bangkok</button>
<button onClick={handleZoomIn}>Zoom In</button>
</div>
</div>
);
}Route Optimization
Basic Optimization
tsx
import { useRouteOptimization } from '@route-optimization/react';
function RouteOptimizer() {
const { status, data, error, isLoading, isSuccess, optimize, reset } = useRouteOptimization({
useMockMode: true, // Use mock mode for development
});
const handleOptimize = async () => {
const request = {
shipments: [
{
id: 'shipment-1',
deliveryLocation: { latitude: 13.7563, longitude: 100.5018 },
},
{
id: 'shipment-2',
deliveryLocation: { latitude: 13.7467, longitude: 100.5352 },
},
],
vehicles: [
{
id: 'vehicle-1',
startLocation: { latitude: 13.7563, longitude: 100.5018 },
},
],
};
try {
const response = await optimize(request);
console.log('Optimization result:', response);
} catch (err) {
console.error('Optimization failed:', err);
}
};
return (
<div>
<button onClick={handleOptimize} disabled={isLoading}>
{isLoading ? 'Optimizing...' : 'Optimize Routes'}
</button>
{isSuccess && data && (
<div>
<h3>Optimization Complete!</h3>
<p>Routes: {data.routes?.length ?? 0}</p>
<p>Total Distance: {data.metrics?.totalDistance ?? 0} km</p>
</div>
)}
{error && <div className="error">Error: {error}</div>}
</div>
);
}Production Mode with Google Cloud
tsx
import { useRouteOptimization } from '@route-optimization/react';
function ProductionOptimizer() {
const { optimize } = useRouteOptimization({
useMockMode: false,
projectId: 'your-google-cloud-project',
credentials: {
client_email: 'service-account@project.iam.gserviceaccount.com',
private_key: process.env.GOOGLE_PRIVATE_KEY,
},
});
// ... rest of component
}Progress Tracking
tsx
import { useRouteOptimization, useOptimizationStatus } from '@route-optimization/react';
function OptimizationWithProgress() {
const { optimize } = useRouteOptimization({ useMockMode: true });
const {
progress,
step,
setProgress,
reset: resetProgress,
} = useOptimizationStatus({
onStart: () => console.log('Optimization started'),
onSuccess: () => console.log('Optimization complete!'),
onError: (error) => console.error('Failed:', error),
});
const handleOptimize = async () => {
resetProgress();
setProgress(0, 'Initializing...');
// Simulate progress
setProgress(25, 'Calculating distances...');
const response = await optimize(request);
setProgress(75, 'Optimizing routes...');
if (response.success) {
setProgress(100, 'Complete!');
}
};
return (
<div>
<button onClick={handleOptimize}>Optimize</button>
<div className="progress">
<div className="progress-bar" style={{ width: `${progress}%` }} />
<p>{step}</p>
</div>
</div>
);
}Complete Example
Combining map rendering with route optimization:
tsx
import { useState } from 'react';
import { useRouteMap, useRouteOptimization, RouteMapView } from '@route-optimization/react';
import type { Route } from '@route-optimization/core';
function CompleteApp() {
const [route, setRoute] = useState<Route | null>(null);
const [locations, setLocations] = useState([
{ lat: 13.7563, lng: 100.5018, name: 'Bangkok' },
{ lat: 13.7467, lng: 100.5352, name: 'Chatuchak' },
{ lat: 13.7307, lng: 100.5418, name: 'Victory Monument' },
]);
const { optimize, isLoading, isSuccess } = useRouteOptimization({
useMockMode: true,
});
const handleOptimize = async () => {
const request = {
shipments: locations.map((loc, i) => ({
id: `shipment-${i}`,
deliveryLocation: { latitude: loc.lat, longitude: loc.lng },
})),
vehicles: [
{
id: 'vehicle-1',
startLocation: { latitude: locations[0].lat, longitude: locations[0].lng },
},
],
};
const response = await optimize(request);
if (response.success && response.routes?.[0]) {
// Convert optimization result to Route format
const optimizedRoute: Route = {
stops:
response.routes[0].stops?.map((stop, i) => ({
id: stop.shipmentId || `stop-${i}`,
location: {
lat: stop.location?.latitude ?? 0,
lng: stop.location?.longitude ?? 0,
},
name: locations[i]?.name ?? `Stop ${i + 1}`,
})) ?? [],
};
setRoute(optimizedRoute);
}
};
return (
<div className="app">
<div className="sidebar">
<h2>Route Optimization</h2>
<div className="locations">
{locations.map((loc, i) => (
<div key={i} className="location-item">
{loc.name}
</div>
))}
</div>
<button onClick={handleOptimize} disabled={isLoading}>
{isLoading ? 'Optimizing...' : 'Optimize Route'}
</button>
{isSuccess && <div className="success">✓ Route optimized successfully!</div>}
</div>
<div className="map-container">
<RouteMapView
apiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY!}
route={route}
mapConfig={{
center: { lat: 13.7563, lng: 100.5018 },
zoom: 12,
}}
/>
</div>
</div>
);
}
export default CompleteApp;TypeScript Support
All hooks are fully typed. Import types from the packages:
tsx
import type {
Route,
Stop,
MapConfig,
OptimizationRequest,
OptimizationResponse,
} from '@route-optimization/core';
import type {
UseRouteMapOptions,
UseRouteMapReturn,
UseMapControlsReturn,
UseRouteOptimizationResult,
} from '@route-optimization/react';Best Practices
1. Environment Variables
Store API keys in environment variables:
env
# .env.local
REACT_APP_GOOGLE_MAPS_API_KEY=your_api_key
REACT_APP_GOOGLE_PROJECT_ID=your_project_id2. Error Handling
Always handle errors properly:
tsx
const { optimize, error } = useRouteOptimization(config);
const handleOptimize = async () => {
try {
const result = await optimize(request);
// Handle success
} catch (err) {
// Handle error
console.error('Optimization failed:', err);
}
};3. Cleanup
Components automatically clean up when unmounted, but you can manually reset:
tsx
useEffect(() => {
return () => {
clearRoute();
reset();
};
}, []);4. Memoization
Memoize large configuration objects:
tsx
const mapConfig = useMemo(
() => ({
center: { lat: 13.7563, lng: 100.5018 },
zoom: 12,
styles: customMapStyles,
}),
[]
);
const { mapRef } = useRouteMap({
apiKey,
...mapConfig,
});Next Steps
- Learn about Vue Integration
- Explore Route Calculation in depth
- Check out API Reference