如何在styled component中使用React DnD?遇连接器报错求替代方案
Hey there, I totally get your frustration—wrapping your styled component in a <div> can mess up carefully crafted layouts, so let's dive into that second solution the error mentions: turning your styled component into a drag source (or drop target) directly.
What the Error Means
React DnD's connectors need to attach to either native DOM elements or components explicitly set up as drag/drop targets. When you tried wrapping your PaneItemText__StyledItem with connectDragSource, you were passing a styled component (a React component, not a native element) to the connector—hence the error. Instead, we need to make the styled component itself the drag source.
Step-by-Step Solution (Function Components with Hooks)
This is the modern approach using React DnD's useDrag hook:
- Create your styled component as usual:
import styled from 'styled-components'; import { useDrag } from 'react-dnd'; const StyledItem = styled.div` // Your existing styles here padding: 1rem; background: #f0f0f0; border-radius: 4px; cursor: grab; `;
- Build a draggable component that binds
useDragto your styled component:
Instead of wrapping the styled component withconnectDragSource, we'll use therefreturned byuseDragto attach drag functionality directly to the styled component:
const DraggableItem = ({ itemData }) => { // Use useDrag to get the drag ref and state const [{ isDragging }, dragRef] = useDrag({ // Define your unique drag type string type: 'LIST_ITEM', // Data to pass when dragging starts item: { id: itemData.id, content: itemData.content }, // Collect drag state for dynamic styling collect: (monitor) => ({ isDragging: monitor.isDragging(), }), }); // Bind the drag ref to your styled component, add dynamic styles if needed return ( <StyledItem ref={dragRef} style={{ opacity: isDragging ? 0.6 : 1 }} > {itemData.content} </StyledItem> ); };
For Class Components (Using Higher-Order Components)
If you're still using class components, wrap your styled component directly with React DnD's DragSource HOC instead of wrapping an instance of it:
import styled from 'styled-components'; import { DragSource } from 'react-dnd'; const StyledItem = styled.div` // Your styles here `; // Define drag source logic const dragSourceSpec = { beginDrag(props) { return { id: props.item.id }; }, }; // Collect drag state and connector function collectDrag(connect, monitor) { return { connectDragSource: connect.dragSource(), isDragging: monitor.isDragging(), }; } // Wrap the StyledItem directly with DragSource const DraggableItem = DragSource('LIST_ITEM', dragSourceSpec, collectDrag)(StyledItem); // Use it like: // <DraggableItem item={yourItemData} />
Why This Works
By attaching the drag source logic directly to your styled component, you're telling React DnD that this component is a valid drag source. Styled components render a native DOM element under the hood, so the connector can attach to that element without needing an extra wrapper <div>. This keeps your layout intact while adding the drag functionality.
Just ensure your styled component is based on a native HTML element (like div, span, etc.)—which it almost certainly is, since styled-components defaults to div if you don't specify another element.
内容的提问来源于stack exchange,提问作者JoeTidee

