I have picked up a React project that uses Polkadot.js from another developer and I'm struggling to understand how to achieve the following:
I want to display a grid of images. The initial part of the image URL is hardcoded in a const.
When the user clicks on a button, the user's account is checked asynchronously to see what NFT's they own. However there isn't an array/object what I need, so I have to create an array using the hardcoded URL, along with the provided number and add the image file extension at the end of the string. eg. imageURL + imageNumber + '.png'
The async function that is called on click is as follows:
const getNFT = async (address: string) => {
const wsProvider = new WsProvider(wsUrl);
const api = await ApiPromise.create({ provider: wsProvider });
// NOTE the apps UI specified these in mega units -> https://polkadot.js.org/docs/api-contract/start/contract.read
// @ts-ignore
const gasLimit = -1;
// Read from the contract via an RPC call
const value = 0; // only useful on isPayable messages -> https://polkadot.js.org/docs/api-contract/start/contract.read
// @ts-ignore
const contract = new ContractPromise(api, abi, contractAddress);
const {gasConsumed, result, output} = await contract.query['psp34::balanceOf'](address, {value: 0, gasLimit: -1}, address);
console.log(JSON.stringify(result.toHuman()));
if (result.isOk) {
// should output 123 as per our initial set (output here is an i32)
// @ts-ignore
setUserNFTCount(output.toHuman());
// @ts-ignore
console.log('Number of NFT you own:', output.toHuman());
// @ts-ignore
for (let i = 0; i <= output.toNumber() - 1; i++) {
console.log ("Getting NFT at index " + i);
const NFTIndexResult = await contract.query['psp34Enumerable::ownersTokenByIndex'](address, { value: 0, gasLimit: -1 }, address, i);
if (NFTIndexResult.result.isOk && NFTIndexResult.output != null) {
console.log(NFTIndexResult);
console.log(NFTIndexResult.output.toHuman())
// @ts-ignore
var pNumber = NFTIndexResult.output.toHuman().Ok.U64;
console.log('NFT number you own:' + pNumber);
var metadata = metadataUrl + pNumber + '.json';
var image = imageUrl + pNumber + '.png';
console.log('TODO, show image: ' + image);
let myImageArray = [];
myImageArray.push(image)
console.log('array = ' + myImageArray);
}
}
} else {
console.error('Error', result.asErr);
}
}
When I check my console, I can see the individual images I want to add to an array within the image variable. But I'm not sure how to add each image into a single array which I can then use to render a grid of the images.
Edit - For further context: When I do a console log, I only see each individual image path per line rather than an array, even when moving the console log outside of the loop eg. (www.somewebsite.com/image1.png or www.somewebsite.com/image2.png)
Declare the array outside the loop so it isn't declaring a new array each iteration.
Example:
const myImageArray = []; // <-- declare prior to loop
// @ts-ignore
for (let i = 0; i <= output.toNumber() - 1; i++) {
console.log ("Getting NFT at index " + i);
const NFTIndexResult = await contract.
query['psp34Enumerable::ownersTokenByIndex'](
address,
{ value: 0, gasLimit: -1 },
address,
i,
);
if (NFTIndexResult.result.isOk && NFTIndexResult.output != null) {
console.log(NFTIndexResult);
console.log(NFTIndexResult.output.toHuman());
// @ts-ignore
var pNumber = NFTIndexResult.output.toHuman().Ok.U64;
console.log('NFT number you own:' + pNumber);
var metadata = metadataUrl + pNumber + '.json';
var image = imageUrl + pNumber + '.png';
console.log('TODO, show image: ' + image);
myImageArray.push(image); // <-- push all into same array
console.log('array = ' + myImageArray);
}
}
Presumably you'll be doing something with myImageArray
after the loop.
You might find it easier to collect the fetched images using an array of Promise objects.
Example:
const promises = Array.from({ length: output.toNumber()})
.map((_, i) => {
return contract.
query['psp34Enumerable::ownersTokenByIndex'](
address,
{ value: 0, gasLimit: -1 },
address,
i,
)
.then(NFTIndexResult => {
if (NFTIndexResult.result.isOk && NFTIndexResult.output != null) {
console.log(NFTIndexResult);
console.log(NFTIndexResult.output.toHuman());
// @ts-ignore
const pNumber = NFTIndexResult.output.toHuman().Ok.U64;
console.log('NFT number you own:' + pNumber);
const metadata = metadataUrl + pNumber + '.json';
const image = imageUrl + pNumber + '.png';
console.log('TODO, show image: ' + image);
return image;
}
});
});
const myImageArray = await Promise.all(promises);
console.log('array = ' + myImageArray);