我正在使用useState
钩子将下拉列表中的值设置为变量。在onDeviceIdChange
内的特定实例中,我将setDeviceId
设置为value
,这是从我正在使用的组件库中的事件发出的。 value
保持我期望的正确值,但是不会立即更新为deviceId
。
我已经阅读了与此问题相关的各种文章,最常见的解决方案似乎是将变量传递给useEffect
的第二个参数
像这样
useEffect(() => {
fetchDeviceIds();
console.log("call back for device id selection", deviceId);
}, [deviceId]);
但这似乎只是为我反复触发fetchDeviceIds
函数,而从未实际调用更改处理程序。我用useEffect
尝试了几种变体,但无法在deviceId
内获得更新后的值
下面是我的初始实现,没有将deviceId
放入useEffect
的第二个参数中
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;
答案 0 :(得分:0)
setDeviceId(value);
console.log(deviceId); //this won't update immediately because setDeviceId is asynchronous!
setState()不会立即使this.state突变,而是创建一个挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,并且可能会批量调用以提高性能。
React不会更新状态,当您在console.log中获取先前的值
对于您而言,您可以将value
用于所有同步操作,因为它是您要设置的新值,或者您可以将setState下面的所有代码移到useEffect
更新
从下面的代码和docs
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])
答案 1 :(得分:0)
SIGHUP
应该看起来像这样:
onDeviceIdChange
,其余代码应进入依赖于const onDeviceIdChange = async (e, { value }) => {
// code for validating value etc
setDeviceId(value);
}
的{{1}}钩子:
useEffect