Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google maps 在React with TypeScript中延迟加载Google地图库_Google Maps_Reactjs_Typescript - Fatal编程技术网

Google maps 在React with TypeScript中延迟加载Google地图库

Google maps 在React with TypeScript中延迟加载Google地图库,google-maps,reactjs,typescript,Google Maps,Reactjs,Typescript,我将按照教程编写一个GoogleMapsReact组件,用于惰性加载库。我已经从gist实现了ScriptCache。我遇到的问题是,代码只显示加载贴图…,而贴图从不渲染。我错过了什么明显的东西 index.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content

我将按照教程编写一个GoogleMapsReact组件,用于惰性加载库。我已经从gist实现了ScriptCache。我遇到的问题是,代码只显示
加载贴图…
,而贴图从不渲染。我错过了什么明显的东西

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
    <title>App</title>
</head>
<body>
<div id="app"></div>
<script src="/Scripts/dist/bundle.js"></script>
</body>
</html>
GoogleapComponent.tsx:

import * as React from "react";
import * as ReactDOM from 'react-dom'

import cache from './ScriptCache'
import GoogleApi from './GoogleApi'

const defaultMapConfig = {}
export const wrapper = (options: any) => (WrappedComponent: any) => {
    const apiKey = options.apiKey;
    const libraries = options.libraries || ['places'];

    class Wrapper extends React.Component<any, any> {
        constructor(props: any, context: any) {
            super(props, context);

            this.state = {
                loaded: false,
                map: null,
                google: null
            }
        }

        scriptCache: any;
        map: any;
        mapComponent: any
        refs: {
            [string: string]: any;
            map: any;
        }

        componentDidMount() {
            const refs: any = this.refs;
            this.scriptCache.google.onLoad((err: any, tag: any) => {
                const maps = (window as any).google.maps;
                const props = Object.assign({}, this.props, {
                    loaded: this.state.loaded
                });

                const mapRef: any = refs.map;

                const node = ReactDOM.findDOMNode(mapRef);
                let center = new maps.LatLng(this.props.lat, this.props.lng)

                let mapConfig = Object.assign({}, defaultMapConfig, {
                    center, zoom: this.props.zoom
                })

                this.map = new maps.Map(node, mapConfig);

                this.setState({
                    loaded: true,
                    map: this.map,
                    google: (window as any).google
                })
            });
        }

        componentWillMount() {
            this.scriptCache = cache({
                google: GoogleApi({
                    apiKey: apiKey,
                    libraries: libraries
                })
            });
        }

        render() {
            const props = Object.assign({}, this.props, {
                loaded: this.state.loaded,
                map: this.state.map,
                google: this.state.google,
                mapComponent: this.refs.map
            })
            return (
                <div>
                    <WrappedComponent {...props} />
                    <div ref='map' />
                </div>
            )
        }

    }

    return Wrapper;
}

export default wrapper;
import * as React from "react";
import * as ReactDOM from 'react-dom'

import GoogleApiComponent from "./GoogleApiComponent";

export class Container extends React.Component<any, any> {
    render() {
    const style = {
        width: '100px',
        height: '100px'
    }
    return (
        <div style={style}>
            <Map google={this.props.google} />
        </div>
    )
    }
}

export default GoogleApiComponent({
    apiKey: 'AIzaSyAyesbQMyKVVbBgKVi2g6VX7mop2z96jBo ' //From Fullstackreact.com
})(Container)

export class Map extends React.Component<any, any> {

    refs: {
        [string: string]: any;
        map: any;
    }
    map: any;

    componentDidMount() {
        this.loadMap();
    }

    componentDidUpdate(prevProps: any, prevState: any) {
        if (prevProps.google !== this.props.google) {
            this.loadMap();
        }
    }

    loadMap() {
        if (this.props && this.props.google) {
            // google is available
            const {google} = this.props;
            const maps = google.maps;

            const mapRef = this.refs.map;
            const node = ReactDOM.findDOMNode(mapRef);

            let zoom = 14;
            let lat = 37.774929;
            let lng = -122.419416;
            const center = new maps.LatLng(lat, lng);
            const mapConfig = Object.assign({}, {
                center: center,
                zoom: zoom
            })
            this.map = new maps.Map(node, mapConfig);
        }
        // ...
    }

    render() {
        return (
            <div ref='map'>
                Loading map...
      </div>
        )
    }
}

即使容器看起来像这样,也不会打印任何内容:

export class Container extends React.Component<any, any> {
    render()
    {
        const style = {
            width: '100px',
            height: '100px'
        }
        return (
            <div style={style}>
                <Map google={this.props.google} />
            </div>
        )
    }
}
导出类容器扩展React.Component{
render()
{
常量样式={
宽度:“100px”,
高度:“100px”
}
返回(
)
}
}
但是,如果我直接在地图参考上设置宽度和高度,它将正确打印。不能以百分比为单位添加宽度和高度

export class Map extends React.Component<any, any> {
...
    render() {
        const style = {
            width: '100vw',
            height: '100vh'
        }
        return (
            <div ref='map' style={style}>
                Loading map...
      </div>
        )
    }
}
导出类映射扩展React.Component{
...
render(){
常量样式={
宽度:“100vw”,
高度:“100vh”
}
返回(
正在加载地图。。。
)
}
}

查看我在这篇帖子上的答案:@NguyenThanh谢谢,但它使用了实验性的计算器,我还收到了
警告:通过主React包访问PropTypes是不推荐的。改用npm的道具类型包。
在我的浏览器中运行时。用当前代码运行。
let counter = 0;
let scriptMap = new Map();

export const ScriptCache = (function (global: any) {
    return function ScriptCache(scripts: any) {
        const Cache: any = {}

        Cache._onLoad = function (key: any) {
            return (cb: any) => {
                let stored = scriptMap.get(key);
                if (stored) {
                    stored.promise.then(() => {
                        stored.error ? cb(stored.error) : cb(null, stored)
                    })
                } else {
                    // TODO:
                }
            }
        }

        Cache._scriptTag = (key: any, src: any) => {
            if (!scriptMap.has(key)) {
                let tag : any = document.createElement('script');
                let promise = new Promise((resolve: any, reject: any) => {
                    let resolved = false,
                        errored = false,
                        body = document.getElementsByTagName('body')[0];

                    tag.type = 'text/javascript';
                    tag.async = false; // Load in order

                    const cbName = `loaderCB${counter++}${Date.now()}`;
                    let cb: any;

                    let handleResult = (state: any) => {
                        return (evt: any) => {
                            let stored = scriptMap.get(key);
                            if (state === 'loaded') {
                                stored.resolved = true;
                                resolve(src);
                                // stored.handlers.forEach(h => h.call(null, stored))
                                // stored.handlers = []
                            } else if (state === 'error') {
                                stored.errored = true;
                                // stored.handlers.forEach(h => h.call(null, stored))
                                // stored.handlers = [];
                                reject(evt)
                            }

                            cleanup();
                        }
                    }

                    const cleanup = () => {
                        if (global[cbName] && typeof global[cbName] === 'function') {
                            global[cbName] = null;
                        }
                    }

                    tag.onload = handleResult('loaded');
                    tag.onerror = handleResult('error')
                    tag.onreadystatechange = () => {
                        handleResult(tag.readyState)
                    }

                    // Pick off callback, if there is one
                    if (src.match(/callback=CALLBACK_NAME/)) {
                        src = src.replace(/(callback=)[^\&]+/, `$1${cbName}`)
                        cb = (window as any)[cbName] = tag.onload;
                    } else {
                        tag.addEventListener('load', tag.onload)
                    }
                    tag.addEventListener('error', tag.onerror);

                    tag.src = src;
                    body.appendChild(tag);
                    return tag;
                });
                let initialState = {
                    loaded: false,
                    error: false,
                    promise: promise,
                    tag
                }
                scriptMap.set(key, initialState);
            }
            return scriptMap.get(key);
        }

        Object.keys(scripts).forEach(function (key) {
            const script = scripts[key];
            Cache[key] = {
                tag: Cache._scriptTag(key, script),
                onLoad: Cache._onLoad(key)
            }
        })

        return Cache;
    }
})(window)

export default ScriptCache;
export class Container extends React.Component<any, any> {
    render()
    {
        const style = {
            width: '100px',
            height: '100px'
        }
        return (
            <div style={style}>
                <Map google={this.props.google} />
            </div>
        )
    }
}
export class Map extends React.Component<any, any> {
...
    render() {
        const style = {
            width: '100vw',
            height: '100vh'
        }
        return (
            <div ref='map' style={style}>
                Loading map...
      </div>
        )
    }
}