metaplex-foundation / js

A JavaScript SDK for interacting with Metaplex's programs
356 stars 182 forks source link

TypeError: Class extends value undefined is not a constructor or null #248

Closed ezeev closed 2 years ago

ezeev commented 2 years ago

We are trying to use this library with a Next.js project and are receiving this error on any page we try to use Metaplex on.

Steps to reproduce:

Node version: v18.7.0

Package.json:

{
  "name": "redacted-web",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook",
    "test-storybook": "test-storybook",
    "eslint": "eslint --max-warnings 0 'src/**/*.{ts,js}'",
    "eslint:fix": "eslint --max-warnings 0 'src/**/*.{ts,js}' --fix",
    "prepare": "husky install"
  },
  "dependencies": {
    "@emotion/cache": "11.7.1",
    "@emotion/react": "11.9.0",
    "@emotion/server": "11.4.0",
    "@emotion/styled": "11.8.1",
    "@google/model-viewer": "^1.12.0",
    "@liqnft/candy-shop": "^0.5.13",
    "@metaplex-foundation/js": "^0.15.0",
    "@mui/icons-material": "5.6.0",
    "@mui/material": "5.6.0",
    "@solana-mobile/wallet-adapter-mobile": "^0.9.0",
    "@solana/wallet-adapter-base": "^0.9.10",
    "@solana/wallet-adapter-react": "^0.15.9",
    "@solana/wallet-adapter-react-ui": "^0.9.12",
    "@solana/wallet-adapter-wallets": "^0.17.1",
    "@solana/web3.js": "^1.50.1",
    "@storybook/jest": "^0.0.10",
    "amazon-cognito-identity-js": "^5.2.8",
    "aws-amplify": "^4.3.19",
    "i18next": "^21.8.13",
    "next": "12.1.4",
    "next-i18next": "^11.0.0",
    "react": "^18.2.0",
    "react-dom": "18.0.0",
    "react-hook-form": "^7.33.0",
    "react-i18next": "^11.18.0",
    "react-infinite-scroll-component": "^6.1.0",
    "react-rewards": "^2.0.4"
  },
  "devDependencies": {
    "@babel/core": "^7.18.2",
    "@storybook/addon-a11y": "^6.5.9",
    "@storybook/addon-actions": "^6.5.9",
    "@storybook/addon-essentials": "^6.5.9",
    "@storybook/addon-interactions": "^6.5.9",
    "@storybook/addon-links": "^6.5.9",
    "@storybook/builder-webpack5": "^6.5.9",
    "@storybook/manager-webpack5": "^6.5.9",
    "@storybook/react": "^6.5.9",
    "@storybook/test-runner": "^0.3.0",
    "@storybook/testing-library": "^0.0.13",
    "@types/node": "17.0.23",
    "@types/react": "18.0.0",
    "@types/react-dom": "18.0.0",
    "@typescript-eslint/eslint-plugin": "^5.27.1",
    "@typescript-eslint/parser": "^5.27.1",
    "babel-loader": "^8.2.5",
    "eslint": "^8.12.0",
    "eslint-config-next": "12.1.4",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-no-only-tests": "^2.6.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-simple-import-sort": "^7.0.0",
    "eslint-plugin-storybook": "^0.5.13",
    "husky": "^8.0.0",
    "jest": "27",
    "prettier": "^2.6.2",
    "typescript": "4.6.3"
  }
}

next.config.js:

const nextConfig = {
  reactStrictMode: true,
  webpack5: true,
  webpack: (config) => {
    config.resolve.fallback = {
      fs: false,
      crypto: false,
      stream: false,
      zlib: false,
      path: false,
    };
    return config;
  },
};

module.exports = nextConfig;

Example Next.js page for testing:


import { Metaplex } from "@metaplex-foundation/js";
import { Button, Grid, Typography } from "@mui/material";
import { WalletNotConnectedError } from "@solana/wallet-adapter-base";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
import type { NextPage } from "next";
import * as React from "react";

const Ex1: NextPage = () => {
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();

  //const mx = new Metaplex(connection); // TypeError: Class extends value undefined is not a constructor or null

  const onClick = React.useCallback(async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const transaction = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: publicKey,
        //toPubkey: Keypair.,
        //toPubkey: Keypair.generate(),
        toPubkey: new PublicKey("REDACTED"),
        lamports: 1,
      })
    );
    const signature = await sendTransaction(transaction, connection);
    const latestBlockHash = await connection.getLatestBlockhash();

    await connection.confirmTransaction({
      blockhash: latestBlockHash.blockhash,
      lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
      signature: signature,
    });
  }, [publicKey, sendTransaction, connection]);

  React.useEffect(() => {
    // also try in useEffect also causes the same error in line 13.
    const mx = new Metaplex(connection);
  }, []);

  return (
    <Grid container padding={4}>
      <Grid item xs={12} textAlign="center">
        <Typography variant="h5">Send One Lamport</Typography>
        <Button variant="contained" onClick={onClick} disabled={!publicKey}>
          Send
        </Button>
      </Grid>
    </Grid>
  );
};

export default Ex1;
ezeev commented 2 years ago

I was able to fix this by bumping our Next.js version, eslint, and eslint-config-next versions to match Metaplex's example. It then worked. Not sure what changed between these minor versions but it resolved the error.

next: 12.1.4 -> 12.1.6 eslint: ^8.12.0 -> ^8.15.0 eslint-config-next 12.1.4 -> 12.1.6