【问题标题】:React google map wont update styles after changing theme (component re-render)?更改主题(组件重新渲染)后反应谷歌地图不会更新样式?
【发布时间】:2021-12-20 06:11:21
【问题描述】:

我的网站中有一个自定义主题(浅色/深色),我也有一个自定义钩子。 我将谷歌地图(react-google-maps)自定义样式放在useMemo 中并将主题设置为依赖项,但是当我更改主题时,地图组件似乎不会重新渲染并应用新颜色。我尝试调试但没有运气。这是我的实现:

export const MapMarkerSelection = compose(
    withProps({
        googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${API_KEY_MAP}&libraries=geometry,drawing,places`,
        loadingElement: <div style={{height: `100%`}} />,
        containerElement: (
            <div style={{height: `400px`, margin: `8px 0 20px`, borderRadius: `0.5rem`, overflow: 'hidden'}} />
        ),
        mapElement: <div style={{height: `100%`}} />,
    }),
    withScriptjs,
    withGoogleMap,
)((props) => {
    const mapRef = useRef();
    const theme = useTheme(); //here is mu custom hook (no issue with this it work fine in other components)

    useEffect(() => {
        setLatMarker(props.markerPosition.latitude);
        setLngMarker(props.markerPosition.longitude);
        mapRef.current.panTo({
            lat: props.markerPosition.latitude,
            lng: props.markerPosition.longitude,
        });
    }, [props.markerPosition, props.markerPosition.latitude, props.markerPosition.longitude]);

    const [latMarker, setLatMarker] = useState(props.markerPosition.latitude);
    const [lngMarker, setLngMarker] = useState(props.markerPosition.longitude);
    const setCallback = useCallback(
        (latLng) => {
            if (props.onSelectPosition) {
                props.onSelectPosition({latitude: latLng.lat(), longitude: latLng.lng()});
                setLatMarker(latLng.lat());
                setLngMarker(latLng.lng());
                mapRef.current.panTo({
                    lat: latLng.lat(),
                    lng: latLng.lng(),
                });
            }
        },
        [props],
    );

    const mapStyle = useMemo(() => {
        console.log('here');
        return [
            {
                featureType: 'water',
                elementType: 'geometry',
                stylers: [
                    {
                        color: theme.BACKGROUND_COLOR, //here I set water color to dark for dark theme and blue for lighr theme
                    },
                    {
                        lightness: 17,
                    },
                ],
            },
            {
                featureType: 'landscape',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#f5f5f5',
                    },
                    {
                        lightness: 20,
                    },
                ],
            },
            {
                featureType: 'road.highway',
                elementType: 'geometry.fill',
                stylers: [
                    {
                        color: '#ffffff',
                    },
                    {
                        lightness: 17,
                    },
                ],
            },
            {
                featureType: 'road.highway',
                elementType: 'geometry.stroke',
                stylers: [
                    {
                        color: '#ffffff',
                    },
                    {
                        lightness: 29,
                    },
                    {
                        weight: 0.2,
                    },
                ],
            },
            {
                featureType: 'road.arterial',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#ffffff',
                    },
                    {
                        lightness: 18,
                    },
                ],
            },
            {
                featureType: 'road.local',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#ffffff',
                    },
                    {
                        lightness: 16,
                    },
                ],
            },
            {
                featureType: 'poi',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#f5f5f5',
                    },
                    {
                        lightness: 21,
                    },
                ],
            },
            {
                featureType: 'poi.park',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#dedede',
                    },
                    {
                        lightness: 21,
                    },
                ],
            },
            {
                elementType: 'labels.text.stroke',
                stylers: [
                    {
                        visibility: 'on',
                    },
                    {
                        color: '#ffffff',
                    },
                    {
                        lightness: 16,
                    },
                ],
            },
            {
                elementType: 'labels.text.fill',
                stylers: [
                    {
                        saturation: 36,
                    },
                    {
                        color: '#333333',
                    },
                    {
                        lightness: 40,
                    },
                ],
            },
            {
                elementType: 'labels.icon',
                stylers: [
                    {
                        visibility: 'off',
                    },
                ],
            },
            {
                featureType: 'transit',
                elementType: 'geometry',
                stylers: [
                    {
                        color: '#f2f2f2',
                    },
                    {
                        lightness: 19,
                    },
                ],
            },
            {
                featureType: 'administrative',
                elementType: 'geometry.fill',
                stylers: [
                    {
                        color: '#fefefe',
                    },
                    {
                        lightness: 20,
                    },
                ],
            },
            {
                featureType: 'administrative',
                elementType: 'geometry.stroke',
                stylers: [
                    {
                        color: '#fefefe',
                    },
                    {
                        lightness: 17,
                    },
                    {
                        weight: 1.2,
                    },
                ],
            },
        ];
    }, [theme.BACKGROUND_COLOR]);

    return (
        <GoogleMap
            ref={mapRef}
            defaultOptions={{
                styles: mapStyle,
            }}
            defaultZoom={12}
            defaultCenter={{lat: latMarker, lng: lngMarker}}
            onClick={({latLng}) => setCallback(latLng)}
        >
            <Marker position={{lat: latMarker, lng: lngMarker}} draggable onDragEnd={({latLng}) => setCallback(latLng)} />
        </GoogleMap>
    );
});

只有当我刷新页面时,地图的新主题才会适用。我该如何解决?

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    主题会不断变化吗?如果没有,只需向GoogleMap 添加一个键,请记住,这将导致地图完全重新渲染,如果用户可以移动地图,可能不是您想要的。

    另外,请检查该库的文档,或在可能的情况下将其发布在此处,这可能是组件内部缓存了 defaultOptions 属性以防止重新渲染。此外,在使用备忘录时,请避免使用 prop={{memoizedValue}} 之类的内容,因为您每次都在创建新对象,最好使用 prop={memoizedValue}。

    <GoogleMap
      ...
      key={theme.BACKGROUND_COLOR}
    />
    

    【讨论】:

    • 我说你应该检查文档,因为有时,引用为 prop 为 default 的组件通常会缓存该 prop 并对其进行内部更改,而忽略更新。 与不受控制的情况相同 &lt;input 它是 defaultValue。因此,请查看文档以获取 options 或类似的道具,或者只是为了在不更改密钥的情况下接受新选项的方法。
    猜你喜欢
    • 1970-01-01
    • 2018-11-16
    • 2017-03-24
    • 2021-01-27
    • 2017-10-23
    • 2022-07-08
    • 2020-05-01
    • 2015-11-03
    • 2019-06-29
    相关资源
    最近更新 更多