React 数组不随 setState 改变

React array not changing with setState

我的数组没有通过 setState getter 添加新条目。

代码:

let calledOut = false;
export default function PayStation () {
    const [records, setRecords] = useState([]);

    // problem snippet
    if (records.length === 0 && !calledOut) {
        calledOut = true;
        fetch('http://localhost:5000/api').then(
            response => response.json()
        ).then(
            data => {
                const payloadRecords = data["records"];
                // returning
                //     [{
                //         "attributes": {
                //             "type": "Contact",
                //             "url": "/services/data/v42.0/sobjects/Contact/0030U00001UPWYKQA5"
                //         },
                //         "Id": "0030U00001UPWYKQA5",
                //         "Name": "Contact25 Sequence Contact Manual Email"
                //     },
                //     {
                //         "attributes": {
                //             "type": "Contact",
                //             "url": "/services/data/v42.0/sobjects/Contact/0030U00001UPWYLQA5"
                //         },
                //         "Id": "0030U00001UPWYLQA5",
                //         "Name": "Contact26 Sequence Contact Manual Email"
                //     }
                // ]
                setRecords((records => [...records, ...payloadRecords]));
                console.log("records size: " + records.length); // why is this still 0?
            }
        );
    }
    // end problem snippet

    return (records.length === 0 ? "loading..." :
        <div style={{
            height: '100vh',
            display: 'flex',
            maxWidth: 600,
            justifyContent: 'space-between',
            alignItems: 'center'
        }} >
            {records}
        </div>
    );
}

我认为更改状态的要求是克隆状态变量(我相信我正在做),而不是为其分配引用并改变引用。

那么,为什么我的数组没有新条目?

组件的主体应该是一个纯函数。副作用(例如数据获取)应该包含在 useEffect 中。以下代码应该有效:

export default function PayStation () {
  const [records, setRecords] = useState([]);

  useEffect(() => {
    const getRecords = () => {
      fetch('http://localhost:5000/api').then(
        response => response.json()
      ).then(
        data => {
          const payloadRecords = data["records"];
          setRecords((records => [...records, ...payloadRecords]));
        }
      );
    }
    
    getRecords()
  }, [])
  
  if (records.length === 0) return "loading..."

  return (
    <div style={{
      height: '100vh',
      display: 'flex',
      maxWidth: 600,
      justifyContent: 'space-between',
      alignItems: 'center'
    }} >
      {records.map((record) => <Record key={record.id} {...record} />)}
    </div>
  );
}

问题似乎是 useState 和 setState 都在同一个调用中 运行...而且由于它们都是异步的,所以 setState 没有设置任何值因为状态还没有被创建。如果您删除了 calledOut 变量,它应该可以正常工作。

这通常是一种糟糕的抓取方式。我建议做

  useEffect(() => {
    // fetch stuff here
  }, []);

因此,这将在创建状态后调用。