Javascript useState钩子有过时的数据
我正在使用Javascript useState钩子有过时的数据,javascript,reactjs,Javascript,Reactjs,我正在使用useStatehook将下拉列表中的值设置为变量。在我的onDeviceIdChange中的特定实例中,我将setDeviceId设置为value,它是从我正在使用的组件库中的事件发出的值保持我期望的正确值,但是它不会立即更新到设备ID 我已经阅读了与此问题相关的各种帖子,最常见的解决方案似乎是将变量传递给useffect import React, { useState, useEffect } from "react"; import axios from "axios"; i
useState
hook将下拉列表中的值设置为变量。在我的onDeviceIdChange
中的特定实例中,我将setDeviceId
设置为value
,它是从我正在使用的组件库中的事件发出的<代码>值保持我期望的正确值,但是它不会立即更新到设备ID
我已经阅读了与此问题相关的各种帖子,最常见的解决方案似乎是将变量传递给useffect
import 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"
}
});
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);
}
}
};
useEffect(() => {
fetchDeviceIds();
}, []);
const handleClear = () => {
setDeviceId("");
setVersionNum("");
setIsLoading(true);
};
return (
<>
<Form.Field required>
<label style={{ display: "block" }}>device Id</label>
<Dropdown
id="deviceId"
value={deviceId}
onChange={onDeviceIdChange}
selection
fluid
placeholder="Please select an device ID"
clearable
options={hardware.map(device => {
return {
text: device.id,
value: device.id,
key: device.id
};
})}
style={{ marginTop: ".33", marginBottom: "2em" }}
/>
</Form.Field>
<Form.Field>
<label style={{ display: "block", marginTop: "2em" }}>Version Number</label>
{isLoading ? (
<Input
loading
iconPosition="left"
fluid
placeholder="Choose an device ID..."
value={versionNum}
/>
) : (
<Input value={versionNum} fluid readOnly />
)}
</Form.Field>
</>
);
};
export default Example;
像这样的
useEffect(() => {
fetchDeviceIds();
console.log("call back for device id selection", deviceId);
}, [deviceId]);
但这似乎只是为我反复启动fetchDeviceID
函数,而从未真正调用更改处理程序。我尝试了useffect
的一些变体,但未能在deviceId
下面是我的初始实现,没有将deviceId
放入useffect
import 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"
}
});
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);
}
}
};
useEffect(() => {
fetchDeviceIds();
}, []);
const handleClear = () => {
setDeviceId("");
setVersionNum("");
setIsLoading(true);
};
return (
<>
<Form.Field required>
<label style={{ display: "block" }}>device Id</label>
<Dropdown
id="deviceId"
value={deviceId}
onChange={onDeviceIdChange}
selection
fluid
placeholder="Please select an device ID"
clearable
options={hardware.map(device => {
return {
text: device.id,
value: device.id,
key: device.id
};
})}
style={{ marginTop: ".33", marginBottom: "2em" }}
/>
</Form.Field>
<Form.Field>
<label style={{ display: "block", marginTop: "2em" }}>Version Number</label>
{isLoading ? (
<Input
loading
iconPosition="left"
fluid
placeholder="Choose an device ID..."
value={versionNum}
/>
) : (
<Input value={versionNum} fluid readOnly />
)}
</Form.Field>
</>
);
};
export default Example;
import React,{useState,useffect}来自“React”;
从“axios”导入axios;
从“语义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);
异步函数fetchDeviceID(){
const url=“/api/hardware”;
试一试{
const response=等待获取(url{
方法:“获取”
});
如果(!response.ok){
setError(response.statusText);
}
const data=wait response.json();
控制台日志(数据);
设置硬件(数据硬件);
}捕获(错误){
日志(“错误捕获”,错误);
log(“处理网络错误”,error.message);
}
}
const versionUrl=“/api/versionUrl”;
const ondevicedchange=async(e,{value})=>{
log(“设备id值-->”,值);
setDeviceId(值);
console.log(deviceId);//这不会立即更新
如果(!设备ID){
handleClear();
返回;
}
试一试{
log(“调用versionUrl”);
const response=fetch(versionUrl{
方法:“张贴”,
正文:JSON.stringify({
deviceId:deviceId
}),
标题:{
“内容类型”:“应用程序/json”
}
});
如果(!response.ok){
setError(response.statusText);
}
const data=response.json();
控制台日志(数据);
setVersionNum(data.version\u num);
设置加载(假);
}捕获(错误){
日志(“错误捕获”,错误);
log(“处理网络错误”,error.message);
}
}
};
useffect(()=>{
fetchDeviceID();
}, []);
常量handleClear=()=>{
setDeviceId(“”);
setVersionNum(“”);
设置加载(真);
};
返回(
设备Id
{
返回{
text:device.id,
值:device.id,
关键字:device.id
};
})}
风格={{marginTop:.33],marginBottom:“2em”}
/>
版本号
{孤岛加载(
) : (
)}
);
};
导出默认示例;
setState()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,并且可能会对调用进行批处理以提高性能
React不会更新状态,当您使用console.log时,您将获得以前的值
在您的情况下,您可以将值
用于所有同步操作,因为它是您正在设置的新值,或者您可以将setState下方的所有代码移动到useffect
import 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"
}
});
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);
}
}
};
useEffect(() => {
fetchDeviceIds();
}, []);
const handleClear = () => {
setDeviceId("");
setVersionNum("");
setIsLoading(true);
};
return (
<>
<Form.Field required>
<label style={{ display: "block" }}>device Id</label>
<Dropdown
id="deviceId"
value={deviceId}
onChange={onDeviceIdChange}
selection
fluid
placeholder="Please select an device ID"
clearable
options={hardware.map(device => {
return {
text: device.id,
value: device.id,
key: device.id
};
})}
style={{ marginTop: ".33", marginBottom: "2em" }}
/>
</Form.Field>
<Form.Field>
<label style={{ display: "block", marginTop: "2em" }}>Version Number</label>
{isLoading ? (
<Input
loading
iconPosition="left"
fluid
placeholder="Choose an device ID..."
value={versionNum}
/>
) : (
<Input value={versionNum} fluid readOnly />
)}
</Form.Field>
</>
);
};
export default Example;
更新
从下面的代码和
第二个参数将是形状{data: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])
onDeviceIdChange
应如下所示:
const onDeviceIdChange = async (e, { value }) => {
// code for validating value etc
setDeviceId(value);
}
其余的代码应该进入依赖于deviceId
的useffect
钩子:
useEffect(fetchId, [deviceId]);
所以在
setDeviceId
之后,我有一个if
块,它检查value
是否存在,如果不存在,它调用的是handleClear
,似乎每次都会触发。因此,我的异步操作永远不会到达try块。您没有向该值传递任何值!它发送数据
它不发送数据
,当登录到更改句柄时,这是未定义的。请考虑不要对其进行分解并打印值,这样依赖于deviceId
的try/catch块的其余部分应该进入useffect
?@DJ2您可以将获取id的代码包装到一个名为fetchId
的函数中,并将其放入useffect