0

I have a problem with understanding how my application that consumes components from a custom component library produces this error (coming from react-dnd):

Invariant Violation: Expected drag drop context

Of course I get that it cannot find the context value that is necessary. However, it seems I am not able to provide a proper context value.

Assume my library looks as follow:

// src/DndComponent.tsx
import * as ReactDnd from "react-dnd";

const DndComponent = () => {
  const [, drag] = ReactDnd.useDrag(
    () => ({
      type: "some-type",
      collect: (monitor) => ({
        isDragging: !!monitor.isDragging(),
      }),
    }),
    []
  );

  return <div ref={drag}>Drag me</div>;
};

export default DndComponent;
// index.ts
export { default as DndComponent } from "./DndComponent";
// package.json
{
  "name": "ui-lib",
  "version": "0.0.1",
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/index.umd.cjs",
  "module": "./dist/index.js",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "peerDependencies": {
    "react": "17.0.2",
    "react-dnd": "14.0.5",
    "react-dnd-html5-backend": "14.0.2"
  },
  "devDependencies": {
    "@types/node": "18.15.11",
    "@types/react": "17.0.45",
    "@vitejs/plugin-react": "3.1.0",
    "@vitejs/plugin-react-swc": "3.2.0",
    "typescript": "4.9.3",
    "vite": "4.1.4",
    "vite-plugin-svgr": "2.4.0"
  },
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.umd.cjs"
    }
  }
}
// vite.config.ts
import { defineConfig } from "vite";
import { resolve } from "path";
import react from "@vitejs/plugin-react-swc";

export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.ts"),
      name: "index",
      fileName: "index",
    },
    rollupOptions: {
      external: ["react", "react-dnd", "react-dnd-html5-backend"],
      output: {
        globals: {
          react: "react",
          "react-dnd": "react-dnd",
          "react-dnd-html5-backend": "react-dnd-html5-backend",
        },
      },
    },
  },
  plugins: [react()],
});

And my application looks like this:

// App.tsx
import React from "react";
import * as ReactDnd from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { DndComponent } from "ui-lib";

function App() {
  return (
    <ReactDnd.DndProvider backend={HTML5Backend}>
      <DndComponent />
    </ReactDnd.DndProvider>
  );
}

export default App;
// package.json
{
  "name": "app-dir",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "npm run build && vite preview"
  },
  "dependencies": {
    "react": "17.0.2",
    "react-dnd": "14.0.5",
    "react-dnd-html5-backend": "14.0.2",
    "react-dom": "17.0.2",
    "ui-lib": "file:../ui-lib"
  },
  "devDependencies": {
    "@types/react": "17.0.45",
    "@types/react-dom": "17.0.17",
    "@vitejs/plugin-react": "3.1.0",
    "typescript": "4.9.3",
    "vite": "4.1.4"
  }
}

As you can see, I am wrapping DndComponent inside ReactDnd.DndProvider which should provide the context value.

If I re-export DndProvider and HTML5Backend from ui-lib and consume these instead of directly from react-dnd and react-dnd-html5-backend, I don't have any issues and everything seems to work as expected:

// index.ts (ui-lib)
export { default as DndComponent } from "./DndComponent";
export { DndProvider } from "react-dnd"; // re-export from 'react-dnd' inside `ui-lib`
export { HTML5Backend } from "react-dnd-html5-backend"; // re-export from 'react-dnd-html5-backend' inside `ui-lib`
// App.tsx (app)
import React from "react";
import { DndComponent, DndProvider, HTML5Backend } from "ui-lib"; // consume from `ui-lib`

function App() {
  return (
    <DndProvider backend={HTML5Backend}>
      <DndComponent />
    </DndProvider>
  );
}

export default App;

I found How to share context between different component libraries in react?, React Context API not working from custom NPM component library or How to share context between multiple libraries? that seem to have a very similar problem.

But as you can see, I already added react-dnd and react-dnd- html5-backend as peerDependencies and added both to the Rollup config's external property as well.

0 Answers0