Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When trying to link an application using MUI v5, application gets "TypeError: Cannot read properties of null (reading 'useContext')" #42554

Open
MatTaNg opened this issue Jun 6, 2024 · 2 comments
Labels
package: material-ui Specific to @mui/material status: waiting for maintainer These issues haven't been looked at yet by a maintainer

Comments

@MatTaNg
Copy link

MatTaNg commented Jun 6, 2024

Steps to reproduce

Link to live example: (required)

Steps:

  1. Copy the package.json, ErrorNotification and index.ts code below and put it in a new project
  2. Run yarn && rollup -c && npm link
  3. Create a new CRA project
  4. Modify app.js to import ErrorNotification
  5. Run yarn && npm link @xxxx/ui-shared-library && npm run start

Current behavior

We are trying to use MUI in our shared library to create shared components for our applications. Our shared application is working fine when it is imported from artifactory and within the shared repo as well.

We have recently decided to locally link our shared repo with our application using yarn link however, we keep running into this error below in applications that use our shared library:

Screenshot 2024-06-06 at 4 09 30 PM

I spun up a CRA and just linked the shared library to create a minimal environment
The only code I modified in the CRA is App.js, I have highlighted the modified code below:

import logo from "./logo.svg";
import "./App.css";
import { ErrorNotification } from "@xxxx/ui-shared-library"; // <-- Modified

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          <ErrorNotification></ErrorNotification> // <-- Modified
        </a>
      </header>
    </div>
  );
}

export default App;

This is simply to import a component in our shared library.
This is what ErrorNotification looks like in our shared repo:

import React from "react";
import { Snackbar, Alert } from "@mui/material";

type ErrorNotificationProps = {
  message?: string;
};

const DEFAULT_ERROR_MESSAGE =
  "Oops! Something went wrong, please try again later.";
const AUTO_HIDE_DURATION = 6000;

export const ErrorNotification = (props: ErrorNotificationProps) => {
  return (
    <Snackbar open={true} autoHideDuration={AUTO_HIDE_DURATION}>
      <Alert severity="error">{props.message ?? DEFAULT_ERROR_MESSAGE}</Alert>
    </Snackbar>
  );
};

Then we export our ErrorNotification in src/index.ts

import { ErrorNotification } from "./Notifications";

export { ErrorNotification };

Here is our package.json in our shared library:

{
  "name": "@xxxx/ui-shared-library",
  "version": "1.0.0",
  "main": "dist/index.js",
  "files": [
    "dist"
  ],
  "private": false,
  "peerDependencies": {
    "@emotion/react": "^11.11.4",
    "@emotion/styled": "^11.11.0",
    "@floating-ui/react-dom": "^2.0.8",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "web-vitals": "^2.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "rollup src/App.tsx --format iife --name ui-shared-library --file bundle.js ",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest",
      "plugin:storybook/recommended"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "publishConfig": {
    "registry": "xxxx"
  },
  "strict-ssl": false,
  "devDependencies": {
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.21.4",
    "@babel/preset-react": "^7.18.6",
    "@babel/preset-typescript": "^7.23.3",
    "@mui/material": "^5.15.19",
    "@mui/icons-material": "^5.3.1",
    "@rollup/plugin-commonjs": "^25.0.7",
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@storybook/addon-essentials": "^7.5.3",
    "@storybook/addon-interactions": "^7.5.3",
    "@storybook/addon-links": "^7.5.3",
    "@storybook/addon-onboarding": "^1.0.8",
    "@storybook/blocks": "^7.5.3",
    "@storybook/preset-create-react-app": "^7.5.3",
    "@storybook/react": "^7.5.3",
    "@storybook/react-webpack5": "^7.5.3",
    "@storybook/testing-library": "^0.2.2",
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^13.0.0",
    "@testing-library/user-event": "^13.2.1",
    "@types/jest": "^27.0.1",
    "@types/node": "^16.7.13",
    "@types/react": "^18.2.18",
    "@types/react-dom": "^18.2.7",
    "babel-loader": "^9.1.3",
    "babel-plugin-named-exports-order": "^0.0.2",
    "eslint-plugin-storybook": "^0.6.15",
    "prettier": "3.1.0",
    "prop-types": "^15.8.1",
    "react-scripts": "5.0.0",
    "rollup": "^2.79.1",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-sass": "^1.12.21",
    "rollup-plugin-typescript": "^1.0.1",
    "rollup-plugin-typescript2": "^0.36.0",
    "sass": "^1.69.5",
    "storybook": "^7.5.3",
    "tslib": "^2.6.2",
    "typescript": "4.8",
    "webpack": "^5.89.0"
  }
}

We use rollup to create our dist folder:
rollup.config.mjs:

import nodeResolvePlugin from "@rollup/plugin-node-resolve";
import { readFileSync } from "fs";
import { defineConfig } from "rollup";
import PeerDepsExternalPlugin from "rollup-plugin-peer-deps-external";
import typescript from "rollup-plugin-typescript";
import sassPlugin from "rollup-plugin-sass";
import commonjsPlugin from "@rollup/plugin-commonjs";

const packageJson = JSON.parse(
  readFileSync("./package.json", { encoding: "utf8" })
);

const config = defineConfig({
  input: "./src/index.ts",
  output: [
    {
      file: packageJson.main,
      format: "es",
      sourcemap: true,
    },
  ],

  plugins: [
    PeerDepsExternalPlugin(),
    nodeResolvePlugin(),
    commonjsPlugin(),
    sassPlugin({
      insert: true,
    }),
    typescript(),
  ],
});

export default config;

Once the environment is set up what we've been doing is in our shared repo we'd run:
yarn
rollup -c
npm unlink @xxxx/ui-shared-library
npm link

Then in the CRA app:
npm unlink @xxxx/ui-shared-library
npm link @xxxx/ui-shared-library
npm run start

Expected behavior

Applications should be able to successfully link to our shared repo for local development

Context

We are trying to link our shared repo with our application locally so changes are instantly reflected on our applications

Your environment

npx @mui/envinfo
  System:
    OS: macOS 14.5
  Binaries:
    Node: 18.14.2 - ~/.nvm/versions/node/v18.14.2/bin/node
    npm: 9.5.0 - ~/.nvm/versions/node/v18.14.2/bin/npm
    pnpm: Not Found
  Browsers:
    Chrome: Not Found
    Edge: Not Found
    Safari: 17.5
  npmPackages:
    @emotion/react:  11.11.4 
    @emotion/styled:  11.11.5 
    @mui/base:  5.0.0-beta.40 
    @mui/core-downloads-tracker:  5.15.19 
    @mui/icons-material: ^5.3.1 => 5.15.19 
    @mui/material: ^5.15.19 => 5.15.19 
    @mui/private-theming:  5.15.14 
    @mui/styled-engine:  5.15.14 
    @mui/system:  5.15.15 
    @mui/types:  7.2.14 
    @mui/utils:  5.15.14 
    @types/react: ^18.2.18 => 18.3.3 
    react:  18.3.1 
    react-dom:  18.3.1 
    typescript: 4.8 => 4.8.4 

Testing on Chrome v125.0.6422.77

Search keywords: useContext, Invalid hook call, npm link, yarn linkn

@MatTaNg MatTaNg added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jun 6, 2024
@zannager zannager added the package: material-ui Specific to @mui/material label Jun 7, 2024
@ZeeshanTamboli
Copy link
Member

Code snippets alone won't help us debug the issue, as the pasted code might differ from your actual code. Please provide a minimal reproduction in a GitHub repository. You can create two separate repositories: one for your shared library and another for your React app.

@ZeeshanTamboli ZeeshanTamboli added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jun 23, 2024
@MatTaNg
Copy link
Author

MatTaNg commented Jun 27, 2024

Here is the dummy app that uses the shared library:
https://github.com/MatTaNg/link-test

Here is a dummy shared library:
https://github.com/MatTaNg/ui-shared-library

Steps to repo:

  1. Run npm install on both repos
  2. rollup -c && npm link on ui-shared repo
  3. npm link ui-shared-library on link-test repo
  4. Run npm run start on link-test repo
  5. Observe useContext error

Removing material from Error Notification component makes the error go away

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: material-ui Specific to @mui/material status: waiting for maintainer These issues haven't been looked at yet by a maintainer
Projects
None yet
Development

No branches or pull requests

4 participants