我正在從 json 中獲取資料。我想在我的 React 組件中顯示該資料。但是每次我嘗試將從 json 回傳的物件傳遞到我的狀態時,它只回傳一個并洗掉前一個,而不是 json 中的整個元素。
這是我的代碼。
const [state, setState] = useState({});
const connection = new Connection("devnet");
const { publicKey } = useWallet();
useEffect(() => {
(async () => {
//if not public key, close
if(!publicKey) return;
//get tokens
let response = await connection.getTokenAccountsByOwner(
publicKey!, // owner here
{
programId: TOKEN_PROGRAM_ID,
}
);
response.value.forEach((e) => {
const accountInfo = SPLToken.AccountLayout.decode(e.account.data);
//get only tokens with value of 1
if ( parseInt(`${SPLToken.u64.fromBuffer(accountInfo.amount)}`) === 1 ) {
const tokenPublicKey = `${new PublicKey(accountInfo.mint)}`
//get the metadata of each NFT
const run = async () => {
const ownedMetadata = await programs.metadata.Metadata.load(connection, await programs.metadata.Metadata.getPDA(tokenPublicKey));
//get only tokens of the collection ...
if (ownedMetadata.data.updateAuthority === "Address_authority") {
//show the json data from arweave
let url= ownedMetadata.data.data.uri;
fetch(url)
.then(res => res.json())
.then((out) => {
setState(prevState => {
// THIS IS NOT WORKING FOR ME :(
return {...prevState, ...out};
});
})
.catch(err => { throw err });
}
};
run();
}
});
})()
}, [connection, publicKey]);
console.log(state)
uj5u.com熱心網友回復:
{...prevState, ...out};創建一個新物件,將所有prevState自己的屬性放在新物件上,然后將所有out自己的屬性放在新物件上(覆寫prevStateif的值prevState也具有這些名稱的屬性)。
聽起來您想要一個陣列,而不是單個物件:
const [state, setState] = useState([]);
然后設定:
setState(prevState => [...prevState, out]);
可能不相關,但這可能是一堆不同的狀態變化(每個元素對應一個response.value)。由于作業是異步的,這也可能導致多次臨時重新渲染。也許你想要,但如果你不想要,你可以完成所有的獲取,然后更新一次狀態。此外,任何時候在 a 中執行異步作業時useEffect,都應該考慮到效果的依賴關系在此期間發生變化或組件已卸載的可能性。像這樣的東西(見***評論):
const [state, setState] = useState({});
const connection = new Connection("devnet");
const { publicKey } = useWallet();
useEffect(() => {
// *** Use a controller to stop when the component unmounts, etc.
const controller = new AbortContoller();
const {signal} = controller;
(async () => {
if (signal.aborted) return; // ***
// If not public key, stop
if (!publicKey) return;
// Get tokens
let response = await connection.getTokenAccountsByOwner(
publicKey!, // owner here
{
programId: TOKEN_PROGRAM_ID,
}
);
// *** Build up the new data in this array (since we skip some elements,
// so we won't have a simple 1:1 mapping of `response.value` elements
// to result elements.
const newState = [];
// *** Wait for all the operations to finish and add their elements to `newState`
await Promise.all(
response.value.map(async (e) => {
const accountInfo = SPLToken.AccountLayout.decode(e.account.data);
// Skip tokens with value other than 1
if (parseInt(`${SPLToken.u64.fromBuffer(accountInfo.amount)}`) !== 1) {
return;
}
const tokenPublicKey = `${new PublicKey(accountInfo.mint)}`;
const ownedMetadata = await programs.metadata.Metadata.load(connection, await programs.metadata.Metadata.getPDA(tokenPublicKey));
// Get only tokens of the collection ...
if (ownedMetadata.data.updateAuthority !== "Address_authority") {
return;
}
// Show the data from arweave
let url = ownedMetadata.data.data.uri;
const response = await fetch(url, {signal}); // *** Pass the signal to `fetch`
if (!response.ok) { // *** This check was missing
throw new Error(`HTTP error ${response.status}`); // Or ignore if you prefer
}
const out = await response.json();
newState.push(out);
})
);
// *** Now we have all of them, do one state update
setState(prevState = [...prevState, ...newState]);
})();
return () => {
// Stop if our dependencies change or the component unmounts
controller.abort();
};
}, [connection, publicKey]);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/386190.html
