如何将useState挂钩与异步调用一起使用以更改数组?

Seb*_*cia 5 javascript reactjs

我正在尝试从放置请求更新数组

const [descriptors, setDescriptors] = useState([]);

const handleDescriptorUpdate = (id, descriptorData) => {
    services
      .putDescriptor(id, descriptorData)
      .then((response) => {
        const descriptorIndex = _.findIndex(descriptors, (e) => e.id === id);
        if (descriptorIndex !== -1) {
          const tempDescriptors = [...descriptors];
          tempDescriptors[descriptorIndex] = response.data;
          setDescriptors(tempDescriptors);
        }
      })
      .catch((error) => {
        console.error(error);
      });
  };
Run Code Online (Sandbox Code Playgroud)

当我一次仅执行1个请求时,这很好用,但是当我单击执行两次承诺的更新的按钮时,而不是散布数组并用新的新值更新旧值,两者都散布了同一数组导致在解决第二个承诺时,它将使用从服务器BUT返回的新值(第二个值)更新状态,将新值(第一个承诺更改的一个)更改为其原始值。

描述符最初由对象数组填充(来自get请求):

[
  {
    "id": 24,
    "name": "Test 4.1",
    "percentage": 0,
    "towerId": "5cfc9200-c04a-11e9-89c0-2dd5d3707b1b"
  },
  {
    "id": 23,
    "name": "Test 3.1",
    "percentage": 0,
    "towerId": "5cfc9200-c04a-11e9-89c0-2dd5d3707b1b"
  }
]
Run Code Online (Sandbox Code Playgroud)

Dar*_*usV 3

我看到您让描述符作为一种状态而不是引用,正如我在上面的评论中所说, useState 不会立即反映更改,因此请在内存中保留数组的一个引用,您可以使用钩子 useRef 来完成此操作,请参阅下一个示例:

const [descriptors, setDescriptors] = useState([]);

const descriptorsReference = useRef(null);

const handleDescriptorUpdate = (id, descriptorData) => {
    services
      .putDescriptor(id, descriptorData)
      .then((response) => {
        const descriptorIndex = _.findIndex(descriptors, (e) => e.id === id);
        if (descriptorIndex !== -1) {
         // Use descriptorsReference instead
          const tempDescriptors = [...descriptorsReference.current];
          tempDescriptors[descriptorIndex] = response.data;
          // Next line is to update the descriptors into descriptors state, this phase doesn't happen immediately 'cause is asynchronous 
          setDescriptors(tempDescriptors);
          // Next line is to update the descriptors in memory, this phase occurs immediately 
          descriptorsReference.current = tempDescriptors
        }
      })
      .catch((error) => {
        console.error(error);
      });
  };
Run Code Online (Sandbox Code Playgroud)