ReasonReact项目用react-sortable-hoc编译报错:variant constructor找不到
Hey there, let’s break down why you’re hitting this frustrating error and how to fix it. I’ve tangled with ReasonReact bindings for JS HOCs like react-sortable-hoc before, so let’s walk through the common issues in your setup:
1. Your Fake React Class Files Are Breaking Type Safety
Creating SortableContainer.js and SortableElement.js to return fake React classes is a red flag here. ReasonReact relies on its own variant-based component type system (like statelessComponent or component), and these raw JS classes don’t map to the variant constructors the compiler is expecting. When you try to use them in your TodoList component, the compiler can’t recognize them as valid ReasonReact components, hence the "variant constructor can't be found" error.
Fix: Delete those fake JS files entirely. Your BuckleScript bindings should directly interface with the real react-sortable-hoc module—no intermediary files needed.
2. Your BuckleScript Bindings Aren’t Typed for ReasonReact Components
Chances are your bindings for sortableContainer() and sortableElement() are returning a raw JS value instead of a properly typed ReasonReact component variant. React HOCs take a component and return a new component, and your bindings need to reflect that type relationship correctly.
Here’s how to rewrite your bindings properly:
/* SortableContainer.re */ module SortableContainer = { [@bs.module "react-sortable-hoc"] external jsSortableContainer: (React.component('props)) => React.component('props) = "SortableContainer"; // Wrap the JS HOC output into a ReasonReact-compatible component let make = (component) => ReasonReact.wrapJsForReason( ~component=jsSortableContainer(component), jsPropsConverter=(jsProps) => jsProps ); }; /* SortableElement.re */ module SortableElement = { [@bs.module "react-sortable-hoc"] external jsSortableElement: (React.component('props)) => React.component('props) = "SortableElement"; let make = (component) => ReasonReact.wrapJsForReason( ~component=jsSortableElement(component), jsPropsConverter=(jsProps) => jsProps ); };
The ReasonReact.wrapJsForReason function converts the raw React component returned by the JS HOC into a variant that the ReasonReact compiler understands.
3. Prop Mismatches in Nested Components
react-sortable-hoc requires that sortable elements receive an index prop. If your SortableElement component isn’t accepting this prop, or if your SortableContainer isn’t passing it correctly, this can trigger type errors that manifest as the variant constructor issue.
Here’s an example of a properly typed SortableElement and how to use it in a container:
/* TodoItem.re */ module SortableTodoItem = { let component = ReasonReact.statelessComponent("SortableTodoItem"); // Include the required `index` prop from react-sortable-hoc let make = (~todo: Todo.t, ~index: int, _children) => { ...component, render: (_self) => <div> {ReasonReact.string(todo.text)} </div>, }; // Wrap the component with the sortableElement HOC let sortable = SortableElement.make(make); }; /* TodoList.re */ module TodoList = { let component = ReasonReact.statelessComponent("TodoList"); let make = (~todos: array(Todo.t), _children) => { ...component, render: (_self) => { let sortedTodos = Array.mapi((index, todo) => <SortableTodoItem.sortable todo todo index index /> )(todos); // Wrap the list with sortableContainer <SortableContainer.make> {ReasonReact.array(sortedTodos)} </SortableContainer.make> }, }; };
Notice how we pass the index prop directly to the sortable item—this is mandatory for react-sortable-hoc to work, and missing it can cause hidden type issues.
Final Steps to Fix
- Delete your fake
SortableContainer.jsandSortableElement.jsfiles - Replace your bindings with the typed versions above
- Ensure your sortable elements accept and receive the required
indexprop - Rebuild your project with
npm run buildorbsb -make-world
This should resolve the variant constructor error by aligning your setup with ReasonReact’s type system and react-sortable-hoc’s requirements.
内容的提问来源于stack exchange,提问作者Jaison Justus

