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.
CodePudding user response:
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.
CodePudding user response:
It seems your issue is that of scope. I assume you are looking to have the array of image url's outside of the async function:
const getNFT = async (address: string) =>
I see you declared a local variable myImageArray
inside the for loop. This will cause a number of issues. It, at minimum, needs to be outside the for loop so you don't override your variable with a new empty array, erasing all your data.
There are a number of approaches to this problem, but probably the best would be to collect your results, similar to your current approach, but then return the values from the function. See the below example:
const myImageArray = []; // Declare your array here so if you fail to retrieve you are returning an empty array (if that is your desired behavior)
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) {
// removed for brevity
var image = imageUrl pNumber '.png'
myImageArray.push(image);
}
}
} else {
console.error('Error', result.asErr);
}
return myImageArray; // return the array, as that is the data you seem to want out of the function
Then you can use your function elsewhere like so:
const imageArray = await getNFT('someAddress')