J'essaie de me familiariser avec la mise en œuvre d'API externes dans React et je souhaite pouvoir utiliser l'API de Google Maps pour afficher une carte dans un composant enfant. Idéalement, je veux comprendre comment faire cela sans aucune bibliothèque externe pour avoir une compréhension fondamentale du processus avant d'utiliser quelque chose comme Axios.
Ma question est la suivante : comment puis-je utiliser l'extrait suivant de la documentation de Google pour l'API dans React ?
<script async defer
src='https://maps.googleapis.com/maps/api/js?key=AIzaSyDZfVO29Iytspv4xz7S68doIoiztiRLhbk&callback=initMap'>
</script>
J'ai essayé de l'utiliser dans mon fichier index.html mais lorsque je fais référence à l'objet google dans un composant enfant de React, j'obtiens une erreur :
./src/Main.js Ligne 114 : 'google' n'est pas défini no-undef
Même si ce n'est pas la façon la plus élégante de procéder, une compréhension de base sur la façon d'implémenter l'API sans bibliothèque externe serait grandement appréciée. Nous vous remercions.
EDIT :
Mon App.js :
import React, { Component } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import Main from './Main';
import logo from './logo.svg';
import './App.css';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
class App extends Component {
render() {
return (
<MuiThemeProvider>
<Main />
</MuiThemeProvider>
);
}
}
export default App;
Mon Main.js :
import React, { Component } from 'react';
import { FlatButton, Dialog, Card, Drawer, Paper, AppBar, Popover, Menu, MenuItem } from 'material-ui';
var items = [
{
id: 0,
name: 'Test 1',
city: 'Toronto',
longitude: 24.42142422,
latitude: 49.24121415,
tags: ['vegan', 'cheap', 'low-calorie'],
reviews: [
{
rating: 5,
reviewText: 'This was an amazing restaurant. Incredibly fast service, a large variety of options, and delicious food. I\'ll be here often',
author: 'Mohammad Sheikh',
date: new Date(),
helpfulCount: 5,
notHelpfulCount: 4
},
{
rating: 2,
reviewText: 'Absolutely horrible. Please stop making food.',
author: 'Dissatisfied Customer',
date: new Date(),
helpCount: 2,
notHelpfulCount: 3
},
],
foods:
[
{
id: 0,
name: 'Salad',
img: 'http://www.images.google.com/',
tags: ['vegan', 'low-calorie', 'cheap'],
nutrition:
{
calories: 300,
fat: 5,
carbs: 40,
protein: 24
},
reviews:
{
rating: 4,
reviewText: 'Decent salad. Would recommend.',
author: 'Vegan Bro',
date: new Date(),
helpCount: 4,
notHelpfulCount: 1
}
},
{
id: 1,
name: 'Pasta',
img: 'http://www.images.google.com/',
tags: ['vegetarian', 'dinner'],
nutrition:
{
calories: 800,
fat: 40,
carbs: 80,
protein: 20
},
reviews:
{
rating: 5,
reviewText: 'Absolutely amazing',
author: 'Food Fan',
date: new Date(),
helpCount: 8,
notHelpfulCount: 4
}
},
],
},
];
const paperStyle = {
height: 100,
width: 100,
margin: 20,
textAlign: 'center',
display: 'table',
position: 'relative',
clear: 'both',
float: 'right',
zIndex: 6
};
const paperContent = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)'
}
class RestaurantDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
}
}
render() {
return (
<Dialog>
</Dialog>
)
}
}
class RestaurantButton extends React.Component {
constructor(props) {
super(props);
}
handleClick = () => {
}
render() {
return (
<FlatButton style={{width: '100%', height: '64px'}} onClick>
{this.props.item.city}
<RestaurantDialog restaurant={this.props.item.name} />
</FlatButton>
)
}
}
class MapComponent extends React.Component {
constructor(props) {
super(props);
this.googleChecker = this.googleChecker.bind(this);
this.renderMap = this.renderMap.bind(this);
}
googleChecker() {
if (!window.google.maps) {
setTimeout(this.googleChecker, 100);
}
else {
this.renderMap();
}
}
renderMap() {
var map = google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: 0, lng: 0}
});
}
componentDidMount() {
this.googleChecker();
}
render() {
const selections = this.props.currentSelections;
const buttons = items.filter((item) => {
for (let i = 0; i < selections.length; i++) {
if (selections.map((selection) => {return selection.toLowerCase()}).indexOf(item.tags[i].toLowerCase()) > -1) {
return true;
}
}}).map((item) => {
return (
<RestaurantButton style={{zIndex: '5'}} item={item} />
)
});
return (
<Paper id='map' zDepth={3} style={{height: '300px', width: '100%', backgroundColor: 'white', position: 'absolute'}}>
{ buttons }
</Paper>
)
}
}
class SelectionIcon extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Paper circle={true} zDepth={5} style={this.props.style} key={this.props.index} onClick={this.props.close} >
<div style={paperContent}>{this.props.item}</div>
</Paper>
)
}
}
class SelectionIcons extends React.Component {
constructor(props) {
super(props);
}
handleSelectionClose = (e) => {
e.currentTarget.open = false;
}
render() {
let currentSelections = this.props.currentSelections.slice();
let list = currentSelections.map((item, i) => {
return (
<Paper circle={true} zDepth={5} style={paperStyle} key={i} onClick={this.handleSelectionClose}>
<div style={paperContent}>{item}</div>
</Paper>
)
});
return (
<div>
{list}
</div>
)
}
}
class Main extends React.Component {
constructor(props){
super(props);
this.state = {
navMenuOpen: false,
currentSelections: []
}
}
handleMenuButtonTouch = (e) => {
this.setState({
anchorEl: e.currentTarget.parentNode,
navMenuOpen: !this.state.navMenuOpen
})
}
handleRequestChange = (change) => {
this.setState({
navMenuOpen: change.open
})
console.log(document.getElementById('test').style);
}
handleMenuClick = (e) => {
let currentSelections = this.state.currentSelections.slice();
if (currentSelections.indexOf(e) > -1) {
currentSelections.splice(currentSelections.indexOf(e), 1);
}
else {
currentSelections.push(e);
}
console.log(currentSelections)
this.setState({ currentSelections });
}
render() {
return (
<div>
<AppBar title='The App' id='test' zDepth={1} onLeftIconButtonTouchTap={this.handleMenuButtonTouch} style={{zIndex: 4}}>
</AppBar>
<Drawer
id='test2'
open={this.state.navMenuOpen}
onRequestChange={() => {this.handleRequestChange;}}
containerStyle={{zIndex: 3, marginTop: '64px'}}>
<Menu>
<MenuItem primaryText='High Protein' onClick={() => this.handleMenuClick('High Protein')} />
<MenuItem primaryText='Vegetarian' onClick={() => this.handleMenuClick('Vegetarian')} />
<MenuItem primaryText='Vegan' onClick={() => this.handleMenuClick('Vegan')} />
</Menu>
</Drawer>
<MapComponent items={items} currentSelections={this.state.currentSelections} />
<SelectionIcons currentSelections={this.state.currentSelections} />
</div>
)
}
}
export default Main;
Mon index.html :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script async defer
src='https://maps.googleapis.com/maps/api/js?key=AIzaSyDZfVO29Iytspv4xz7S68doIoiztiRLhbk'>
</script>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>