[英]React UseEffect Updating State but no Rerender
I have an extremely simple issue in which I would like to load input devices and list them.我有一个非常简单的问题,我想加载输入设备并列出它们。 The Web API for Media Devices shows it returns a promise, so I assumed I would have to load this into the state with a useEffect hook.
The Web API for Media Devices shows it returns a promise, so I assumed I would have to load this into the state with a useEffect hook.
React Developer tools shows a list of strings in the inputs array, although the state does not update. React Developer 工具在输入数组中显示字符串列表,尽管 state 不会更新。
const App = () => {
const [inputs, setInputs] = useState([]);
useEffect(() => {
let inputDevices = [];
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices.forEach((device) => inputDevices.push(device.label));
});
setInputs([inputDevices]);
}, []);
return (
<div>
<ol>
{inputs.map((device, index) => {
return (
<li key={index}>
id:{index} - Device: {device}{" "}
</li>
);
})}
</ol>
</div>
);
output: output:
edit: the setinputs([inputDevices]) was an accident, thank you all who reminded me about the asynchronicity of the promise:)编辑: setinputs([inputDevices]) 是个意外,谢谢所有提醒我 promise 的异步性的人:)
The issue is setInputs
will be execute before the then
callback, so you need to setInputs
inside the then
callback, and you can use map
to get the list of labels
.问题是
setInputs
将在then
回调之前执行,因此您需要在then
回调中map
setInputs
labels
列表。
let inputDevices = [];
navigator.mediaDevices.enumerateDevices().then((devices) => {
setInputs(devices.map((device) => device.label))
});
let inputDevices = [];
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices.forEach((device) => inputDevices.push(device.label));
});
setInputs([inputDevices]);
You need to call set state inside then
. then
你需要在里面调用 set state 。 Promises are resolved asynchronously hence when you call setInputs
where you have it by that time data isn't there yet. Promise 是异步解决的,因此当您调用
setInputs
时,到那时数据还不存在。
You can also just utilize map
:您也可以只使用
map
:
setInputs(devices.map((device) => device.label)) // inside .then
Promises are resolved asynchronously so you need to push the setInputs(inputDevices) inside then. Promise 是异步解决的,因此您需要将 setInputs(inputDevices) 推入其中。
You can change your code too,您也可以更改代码,
navigator.mediaDevices.enumerateDevices().then((devices) => {
return devices.map(device => device.label);
})
.then(transformedArray => setInputs(transformedArray))
And one more thing in your code, you are setting the state like this在您的代码中还有一件事,您正在像这样设置 state
setInputs([inputDevices]); // like an array inside array
But inside your code, you are accessing it like,但是在您的代码中,您可以像访问它一样,
{inputs.map((device, index) => {
return (
<li key={index}>
id:{index} - Device: {device}{" "}
</li>
);
})}
So change it to,所以改成,
inputs[0].map()
or update the state like this,或像这样更新 state,
setInputs(inputDevices)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.