为了账号安全,请及时绑定邮箱和手机立即绑定

useState 钩子有陈旧的数据

useState 钩子有陈旧的数据

繁花如伊 2021-11-18 10:07:20
我正在使用useState钩子将下拉列表中的值设置为变量。在我的特殊情况下里面onDeviceIdChange,我设置setDeviceId到value它是由组件库我使用的是事件发出。value拥有我期望的正确值,但它不会deviceId立即更新。我已经阅读了与此问题相关的各种帖子,最常见的解决方案似乎是将变量传递给第二个参数 useEffect所以像这样  useEffect(() => {    fetchDeviceIds();    console.log("call back for device id selection", deviceId);  }, [deviceId]);但这似乎只是fetchDeviceIds为我重复触发该函数,而从未真正调用更改处理程序。我已经尝试了一些变体,useEffect但无法在里面获得更新的值deviceId下面是我的初始实现,没有放入deviceId第二个参数useEffectimport React, { useState, useEffect } from "react";import axios from "axios";import { Dropdown, Form, Input } from "semantic-ui-react";const Example = props => {  const [deviceId, setDeviceId] = useState("");  const [hardware, setHardware] = useState([]);  const [error, setError] = useState("");  const [versionNum, setVersionNum] = useState("");  const [isLoading, setIsLoading] = useState(true);  async function fetchDeviceIds() {    const url = "/api/hardware";    try {      const response = await fetch(url, {        method: "GET"      });      if (!response.ok) {          setError(response.statusText);      }      const data = await response.json();      console.log(data);         setHardware(data.hardware);    } catch (error) {      console.log("error catch", error);      console.log("Handle networking errors", error.message);    }  }  const versionUrl = "/api/versionUrl";  const onDeviceIdChange = async (e, { value }) => {    console.log("device id value --> ", value);    setDeviceId(value);    console.log(deviceId); //this won't update immediately    if (!deviceId) {      handleClear();      return;    }      try {        console.log("calling versionUrl");        const response = fetch(versionUrl, {          method: "POST",          body: JSON.stringify({            deviceId: deviceId          }),          headers: {            "Content-Type": "application/json"          }        });
查看完整描述

2 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

onDeviceIdChange 应该是这样的:


const onDeviceIdChange = async (e, { value }) => {

    // code for validating value etc

    setDeviceId(value);

}

其余的代码应该进入useEffect依赖于的钩子deviceId:


useEffect(fetchId, [deviceId]);


查看完整回答
反对 回复 2021-11-18
?
饮歌长啸

TA贡献1951条经验 获得超3个赞

setDeviceId(value);

console.log(deviceId); //this won't update immediately because setDeviceId is asynchronous!

setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。无法保证对 setState 调用的同步操作,并且可能会批量调用以提高性能。


React 不会更新状态,当您使用 console.log 时,您会获得先前的值


在您的情况下,您可以使用valuefor all 同步操作,因为它是您正在设置的新值,或者您可以将 setState 下面的所有代码移动到 auseEffect


更新


从下面的代码和文档


onChange={onDeviceIdChange}

第二个参数将是形状的对象,{data: value} 因此您的参数value将始终未定义!


const onDeviceIdChange = async (e, {value}) => {

    console.log("device id value --> ", value);

    console.log("device value from event --> ", e.target.value);

    setDeviceId(value);

  };


useEffect(() => {

    if (!deviceId) {

      handleClear();

      return;

    }

      try {

        console.log("calling versionUrl");

        const response = fetch(versionUrl, {

          method: "POST",

          body: JSON.stringify({

            deviceId: deviceId

          }),

          headers: {

            "Content-Type": "application/json"

          }

        });


        if (!response.ok) {

          setError(response.statusText);

        }

        const data = response.json();

        console.log(data);

        setVersionNum(data.version_num);

        setIsLoading(false);

      } catch (error) {

        console.log("error catch", error);

        console.log("Handle networking errors", error.message);

      }

    }

},[deviceId])


查看完整回答
反对 回复 2021-11-18
  • 2 回答
  • 0 关注
  • 204 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信