我正在尝试使用javascript API从Airtable加载数据。但是当我尝试在承诺块中设置数据状态时,承诺并没有"结束"。
空气表API的东西:
export const listRecords = function() {
const Airtable = require('airtable');
const base = new Airtable({ apiKey: apiKey }).base(baseId);
const list = base(tableName)
.select({ view: 'Grid view' }).all().then(records => {
return records;
}).catch(err => {
if (err) {
console.error(err);
return null;
}
});
return list;
};
设置状态的东西:
const [state, setState] = useState({
records: []
});
Promise.all([listRecords()]).then((v) => {
setState((s) => ({ ...s, records: v }));
});
然后,当我在 promise 语句之前、内部或之后放置控制台.log时,它们会在无休止的循环中被调用。所以我的问题是,我如何使承诺只被调用/完成一次?
如果你只希望你的 Promise 在挂载上运行,请把它放在一个具有空依赖项数组的效果中:
function YourComponent(props) {
const [state, setState] = useState({
records: []
});
useEffect(() => {
Promise.all([listRecords()]).then((v) => {
setState((s) => ({ ...s, records: v }));
});
}, []);
}
[]
意味着效果只会在初始挂载时运行一次。如果您希望在其他值更改时调用listRecords()
,请将这些值放在 Array 中:
function YourComponent({ id }) {
const [state, setState] = useState({
records: []
});
useEffect(() => {
Promise.all([listRecords(id)]).then((v) => {
setState((s) => ({ ...s, records: v }));
});
}, [id]);
}
在你的例子中,看起来你在不使用useEffect的情况下调用promise。任何 API 调用和状态更新都应在 useEffect 中调用。否则,将会有无限数量的更新,因为 setState 会一遍又一遍地重新渲染组件并调用 promise。