Can't assign variables to getNFTs() options function in react typescript

Hi,

I can’t use a variable with the same values in the getNFTs() options, this is because it expects:

chain?: "eth" | "0x1" | "ropsten" | "0x3" | "rinkeby" | "0x4" | "goerli" | "0x5" | "kovan" | "0x2a" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "localdevchain" | "dev" | undefined;

But when I have a multichain application I would have to use a switch for each chain, whilst when being able to use a variable I can just update the value of the variable and not needing to use a switch statement. See below for example:

image

I can’t assign a variable to the options here since it needs a literal string. Of course if you update it to accept a String Object there could be errors when people don’t fill in the correct data, but I think in my opinion this would be a nice addition.

      switch (networkName) {
        case "eth": {
          const userAddr = user?.get("ethAddress");
          const fetchNFTs = async () => {
            const response = await account.getNFTs({
              chain: "eth",
              address: userAddr,
            });
            const nftArray = response.result!;
            nftArray.sort((a, b) =>
              a.name > b.name ? 1 : b.name > a.name ? -1 : 0
            );

            let mapped: Map<string, NFT[]> = mapIt(nftArray);
            setMappedItems(createMappingArray(mapped));
          };
          fetchNFTs();
          break;
        }
        case "rinkeby": {
          const userAddr = user?.get("ethAddress");
          const fetchNFTs = async () => {
            const response = await account.getNFTsForContract({
              chain: "rinkeby",
              address: userAddr,
            });
            const nftArray = response.result!;
            nftArray.sort((a, b) =>
              a.name > b.name ? 1 : b.name > a.name ? -1 : 0
            );

            let mapped: Map<string, NFT[]> = mapIt(nftArray);
            setMappedItems(createMappingArray(mapped));
          };
          fetchNFTs();
          break;
        }
        case "polygon": {
          const userAddr = user?.get("ethAddress");
          const fetchNFTs = async () => {
            const response = await account.getNFTs({
              chain: "polygon",
              address: userAddr,
            });
            const nftArray = response.result!;
            nftArray.sort((a, b) =>
              a.name > b.name ? 1 : b.name > a.name ? -1 : 0
            );
            let mapped: Map<string, NFT[]> = mapIt(nftArray);

            setMappedItems(createMappingArray(mapped));
          };
          fetchNFTs();
          break;
        }
      }

For the current state I need to use 3 cases. While when I can just use a variable value:

const userAddr = user?.get("ethAddress");
          const fetchNFTs = async () => {
            const response = await account.getNFTs({
              chain: chainName,
              address: userAddr,
            });
            const nftArray = response.result!;
            nftArray.sort((a, b) =>
              a.name > b.name ? 1 : b.name > a.name ? -1 : 0
            );

            let mapped: Map<string, NFT[]> = mapIt(nftArray);
            setMappedItems(createMappingArray(mapped));
          };
          fetchNFTs();

Notice the chain: chainName, I can use redux to assign this variable to a selector so it updates automatically when application state changes.

Don’t know if this update is possible but would be nice :slight_smile:
Happy to know the answer :smiley:

What happens when you name your variable chain as well and directly pass in the arguments?
Like -

let chain = "eth"

const response = await account.getNFTs({
              chain,
              address: userAddr,
            });


Doesn’t work unfortunately, It expects a literal string like ‘eth’, not a variable value. Probably because it’s stated as {chain?: 'eth' | 'rinkeby' | etc.}

I am getting the same error.
@malik

Seems we need to fix that type !

1 Like

Would love to see one, that’s why I suggested it :wink:

it works for me

const chain = 'ropsten';
const options = { chain: chain, address: '0x25587E1b01DF7c8530f7852935E09F98a8eB48D1' };
const response = await Moralis.Web3API.account.getNFTs(options);

We are discussing react-moralis typescript.

Doesn’t work with react-typescript :sweat_smile:

The function just needs to be updated to also be compatible with typescript and to accept also a string type itself, for example:

chain?: "eth" | "0x1" | "ropsten" | "0x3" | "rinkeby" | "0x4" | "goerli" | "0x5" | "kovan" | "0x2a" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "localdevchain" | "dev" | undefined | string; 

Notice the string type at the end.
I think this way it allows devs to pass a variable type in the chain option.

I ‘fixed’ the error by updating the useMoralisWeb3Api.d.ts file with the method given above (add type string as acceptable option).

image

Now I won’t have this in my own project, because I’m here updating a node modules file of the sdk, which should not be done. But Moralis can update the file and push a new update so all users get the update and can npm install to get the new version :wink:
In the photo the IDE is not coloring the string as a type, because I did not place it on the same line to fit it in the picture.

After doing this locally and running my application the change works fine, so the fix to this problem is to add the string type as an acceptable option to the getNFTs() options function.

Yeh.
Go it.
I didn’t realize you were using Typescript.
It makes sense now.

Yeah. It’s not working from here as well. We will see if we can do something about it.

1 Like

Awesome, hope there will be a fix :+1:

This issue comes from the fact that you use let chainName = eth. So Typescript will consider this variable chainName as any string. The best way to fix this is on your end and tell Typescript what values chainName can be. For example:

let chainName: 'eth' | 'bsc' = 'eth'

We will not change it in the type definitions as this will make the type checking less strict. If we add string as a possible type. Then users won’t get any warning if they provide invalid values (as we accept any string). So then chain: 'bitcoin' would be accepted, which is invalid.

5 Likes

I see, your option has worked for me. :+1:

  useEffect(() => {
    if (isAuthenticated) {
      let chain: "eth" | "rinkeby" | "polygon";
      if (networkName == "eth") {
        chain = "eth";
      } else if (networkName == "rinkeby") {
        chain = "rinkeby";
      } else {
        chain = "polygon";
      }
      const userAddr = user?.get("ethAddress");
      const fetchNFTs = async () => {
        const response = await account.getNFTs({
          chain,
          address: userAddr,
        });
        const nftArray = response.result!;
        nftArray.sort((a, b) =>
          a.name > b.name ? 1 : b.name > a.name ? -1 : 0
        );

        let mapped: Map<string, NFT[]> = mapIt(nftArray);
        setMappedItems(createMappingArray(mapped));
      };
      fetchNFTs();
    }
  }, [chainId]);

It is now accepted by the getNFTs options.
chainId is a variable that changes when user switches network.

2 Likes