React无法使用useEffect()中的钩子设置状态

时间:2019-12-12 14:09:35

标签: reactjs set react-hooks use-effect

我是个新手,因此决定开发一个简单的气象应用程序。页面加载后,我希望该应用程序询问用户地理定位,然后相应地显示气象数据。

function App() {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(async (position) => {
      let { latitude, longitude } = position.coords;
      const data = await getWeatherByCords(latitude, longitude);
      await setWeather(data); // Line 8
      console.log(weather) //outputs undefined
      setWeather('hhello'); // Line 10
      console.log(weather) //outputs undefined
      let address = await cordsToAddress(latitude, longitude);
    });
  },[]);


  return (
    <div className="App">
      <h3>Weather App</h3>
      <Weather
        data={weather.data}
      />
    </div>
  );
}

export default App;

getWeatherByCords()只是一个辅助函数,它将请求发送到天气api并返回其响应

我了解到useEffect(() => {},[])钩子等于componentDidMount(),据我了解,该钩子仅在页面加载或刷新时才触发,请纠正我的错误

当我尝试将weather设置为接收到的数据或仅将其用于某个字符串的测试,然后再将其传递到<Weather/>组件中时,在某些情况下,这两种情况均无法使用原因以及当我尝试在控制台中登录weather时,在两种情况下都无法定义。

我还应该等待设置天气(如第8行)还是不(如第10行)?

1 个答案:

答案 0 :(得分:1)

我仔细阅读了钩子,并自己弄清楚了。

function App() {
  const [weather, setWeather] = useState({});

  useEffect(() => console.log(weather), [weather]);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(async (position) => {
      let { latitude, longitude } = position.coords;
      const data = await getWeatherByCords(latitude, longitude);
      console.log('setting weather');
      setWeather(data);
      let address = await cordsToAddress(latitude, longitude);
    });
  }, []);


  return (
    <div className="App">
      <h3>Weather App</h3>
      <Weather
        data={weather}
      />
    </div>
  );
}

我以前的代码实际上是在设置天气,但是它是异步的,因此console.log()没有捕获它。因此,我写了一个钩子,记录了weather的变化,以便随时进行控制台操作( this question对我有很大帮助

useEffect(() => console.log(weather), [weather]);

PS 我遇到的另一个问题是我的组件正在“刷新”并几乎不断发送api请求,并且由于我只想在页面加载或刷新时发送api请求,所以我也将navigator代码包装在了useEffect()中钩子:

useEffect(() => {
  navigator.geolocation.getCurrentPosition(async (position) => {
    // code related to working with apis
  });
}, []);