简体   繁体   English

反应 UseEffect 更新 State 但没有重新渲染

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM