使用API​​的异步调用setState后状态为空(挂钩)

我正在尝试使用从城市名称返回经度和纬度的地理编码定位器。应该将其设置为州并用于在地图上显示城市。我可以设法很好地获取结果,但是,当我尝试设置状态时,状态为null。

这是地图组件的代码:

import React, { useState, useEffect } from "react";
import MapGL, { GeolocateControl } from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";
import { OpenStreetMapProvider } from "leaflet-geosearch";

const Map = (props) => {
  const [long, setLong] = useState(null);
  const [lat, setLat] = useState(null);

  useEffect(() => {
    getCoords();
  }, []);

  const TOKEN =
    "xxx.xxx.xxxx-xxxxx";

  const [viewport, setViewPort] = useState({
    width: "20%",
    height: 400,
    latitude: 6.122498,
    longitude: 80.112597,
    zoom: 12,
  });

  const _onViewportChange = (viewport) =>
    setViewPort({ ...viewport, transitionDuration: 3000 });

  const getCoords = async () => {
    // setup
    const provider = new OpenStreetMapProvider();

    // search
    const results = await provider.search({ query: props.currentCity });
    console.log(results[0].x)
    console.log(results[0].y)
    setLong({ long: results[0].x });
    setLat({ lat: results[0].y });

    console.log(long);
    console.log(lat)
  };
  return (
    <div style={{ margin: "0 auto" }}>
      <MapGL
        {...viewport}
        mapboxApiAccessToken={TOKEN}
        mapStyle="mapbox://styles/mapbox/dark-v8"
        onViewportChange={_onViewportChange}
      ></MapGL>
    </div>
  );
};

export default Map;

我已经将一些值预设为纬度和经度,并且依赖控制台。日志,因此应用程序不会中断。

    console.log(results[0].x)
    console.log(results[0].y)
    setLong({ long: results[0].x });
    setLat({ lat: results[0].y });

    console.log(long);
    console.log(lat)

前两个日志显示的位置很好。最后两个输出状态的初始状态,即:null。

城市名称来自道具,而道具则来自不同的组件,并且确实可以正常工作。

            <Map currentCity={currentCity}/>

我敢肯定这是愚蠢的,但是我一生都无法弄清楚。 该地图是一个地图框,我正在使用传单中的OpenStreetMapProvider。

我尝试过其他提供商,但没有成功。我很确定自己在异步通话中做错了什么。我认为状态是在通话结束之前设置的。我已经尝试过使用诺言,但没有任何改变。

谢谢。

评论
  • 纠缠
    纠缠 回复

    long and lat are local consts. They can never change, and that's not what setLong and setLat are trying to do. The purpose of setting state is to tell react to rerender the component. When that new render happens, new local variables will be created with the new values.

    因此,除了将log语句放置在无用的地方之外,一切都按预期进行。如果您想查看新值,请将log语句放在组件主体中

      const [long, setLong] = useState(null);
      const [lat, setLat] = useState(null);
      console.log('rendering', lat, long);
    
  • Young
    Young 回复

    由于其异步方法:

    setLong({ long: results[0].x }); // <--- This is async
    setLat({ lat: results[0].y }); // <--- This is async
    
    console.log(long); // <--- So,You will not get direct updated value
    console.log(lat) // <--- So,You will not get direct updated value
    

    设置该值后,您的dom将被渲染,

    因此,请放心,您将在放置JSX的return中获得这些值。