使用 useState 钩子将项目添加到以 React 状态存储的数组的正确方法?

IT技术 arrays reactjs use-state
2022-08-01 00:54:30

我需要将项目连接到存储在 React 组件状态中的数组。我有一个关于 stackblitz 的示例,我无法理解为什么数组没有增长,因为我使用扩展运算符添加元素以连接到现有数组。任何帮助表示赞赏

链接:https ://stackblitz.com/edit/react-usestate-example-ebzt6g?file=index.js

import React from 'react';
import { useState, useEffect } from 'react';
import { render } from 'react-dom';
import './style.css';

const App = () => {

    const [name, setName] = useState('React');
    const [coords, setCoords] = useState([]);

    const success = (position) => {
        // setCoords(coords.concat(position.coords))
        setCoords([
            ...coords,
            position.coords
        ])
        console.log("success! position=", position);
    }

    useEffect(() => {
        console.log("useEffect -> coords =", coords);
    });

    useEffect(() => {
        setInterval(() => {
            success({coords : {latitude: Math.random()*51, longitude: Math.random()*2.6}});
        }, 5000);
    }, []);

    return (
    <p>example to demonstrate growing an array stored with React usestate hook</p>
    )
}

render(<App />, document.getElementById('root'));


3个回答
useEffect(() => {
  setInterval(() => {
    success({coords : {latitude: Math.random()*51, longitude: Math.random()*2.6}});
  }, 5000);
}, []);

作为第二个参数的空数组告诉 react 只创建一次这个效果,并且永远不会更新它。当它被创建时,它在其闭包中有一个对成功函数的引用,而该成功函数又对coords. 由于这全部来自第一次渲染,coords因此是一个空数组。

因此,每次调用success时,都会将新坐标添加到该空数组并调用 setCoords。数组永远不会增长,因为您的起点始终是空数组。而且你永远不会看到新的数组,因为它们只存在于以后的渲染中。

最简单的解决方法是使用 setCoords 的函数版本。React 将调用该函数并传入坐标的最新值

const success = (position) => {
  setCoords(prevCoords => {
    return [
      ...prevCoords,
      position.coords
    ]
  })
}

感谢尼古拉斯塔的正确答案。

const success = (position) => {
  setCoords(prevCoords => {
    return [
      ...prevCoords,
      position.coords
    ]
  })
}

解决了这个问题。

好吧,我遇到了这个问题,感谢帮助我弄清楚如何解决这个问题的人,首先你必须克隆坐标,然后你将新坐标添加到克隆中,然后将新的克隆坐标设置为状态像这样:

 const success = (position) => {
  let clonedCoords = [...coords];
  setCoords([...clonesCoords, position.coords]);
  console.log("success! position=", position);
};

这应该可以,如果不行,你可以回复,这样我可以帮助你更多