我开始从http://react-dnd.github.io/react-dnd/docs-tutorial.html
学习React Drag and Drop但是我在理解教程时遇到了问题。接下来是我创建的所有文件,但在编译时我得到:
dragDropBundle.js:830 Warning: Failed prop type: The prop
`connectDropTarget` is marked as required in `BoardSquare`, but its value is `undefined`.
in BoardSquare (created by Board)
in Board (created by DragDropContext(Board))
in DragDropContext(Board)
和
dragDropBundle.js:31408 Uncaught TypeError: connectDropTarget is not a function
at BoardSquare.render (dragDropBundle.js:31408)
at dragDropBundle.js:16370
有人可以解释一下我有什么问题吗?我正在阅读本教程几次并用它来敲墙。
这是我的程序开始的文件entry.js
的内容:
import React from "react";
import ReactDOM from "react-dom";
import Square from "./Square.jsx";
import Board from "./Board.jsx";
import Knight from "./Knight.jsx";
import { observe } from "./Game.jsx";
import { canMoveKnight, moveKnight } from "./Game.jsx";
const rootEl = document.getElementById("root");
observe(knightPosition =>
ReactDOM.render(<Board knightPosition={knightPosition} />, rootEl)
);
这是我的文件Board.jsx
的内容:
import React, { Component } from "react";
import { DragDropContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import PropTypes from "prop-types";
import Square from "./Square.jsx";
import Knight from "./Knight.jsx";
import { canMoveKnight, moveKnight } from "./Game.jsx";
import { BoardSquare } from "./BoardSquare.jsx";
export class Board extends Component {
renderPiece(x, y) {
const [knightX, knightY] = this.props.knightPosition;
if (x === knightX && y === knightY) {
return <Knight />;
}
}
renderSquare(i) {
const x = i % 8;
const y = Math.floor(i / 8);
return (
<div key={i} style={{ width: "12.5%", height: "12.5%" }}>
<BoardSquare x={x} y={y}>
{this.renderPiece(x, y)}
</BoardSquare>
</div>
);
}
handleSquareClick(toX, toY) {
if (canMoveKnight(toX, toY)) {
moveKnight(toX, toY);
}
}
render() {
console.log(this.props.knightPosition);
const squares = [];
for (let i = 0; i < 64; i++) {
squares.push(this.renderSquare(i));
}
return (
<div
style={{
width: "100%",
height: "100%",
display: "flex",
flexWrap: "wrap"
}}
>
{squares}
</div>
);
}
}
Board.propTypes = {
knightPosition: PropTypes.arrayOf(PropTypes.number.isRequired).isRequired
};
export default DragDropContext(HTML5Backend)(Board);
这是我的文件Knight.jsx
的内容:
import React, { Component } from "react";
import PropTypes from "prop-types";
import { ItemTypes } from "./Constants.jsx";
import { DragSource } from "react-dnd";
const knightSource = {
beginDrag(props) {
return {};
}
};
function collect(connect, monitor) {
return {
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging()
};
}
class Knight extends Component {
render() {
const { connectDragSource, isDragging } = this.props;
return connectDragSource(
<div
style={{
opacity: isDragging ? 0.5 : 1,
fontSize: 25,
fontWeight: "bold",
cursor: "move"
}}
>
♘
</div>
);
}
}
Knight.propTypes = {
connectDragSource: PropTypes.func.isRequired,
isDragging: PropTypes.bool.isRequired
};
export default DragSource(ItemTypes.KNIGHT, knightSource, collect)(Knight);
这是我的文件Square.jsx
的内容:
import React, { Component } from "react";
import PropTypes from "prop-types";
export default class Square extends Component {
render() {
const { black } = this.props;
const fill = black ? "black" : "white";
const stroke = black ? "white" : "black";
return (
<div
style={{
backgroundColor: fill,
color: stroke,
width: "100%",
height: "100%"
}}
>
{this.props.children}
</div>
);
}
}
Square.propTypes = {
black: PropTypes.bool
};
这是我文件的内容:BoardSquare.jsx
import React, { Component } from "react";
import PropTypes from "prop-types";
import Square from "./Square.jsx";
import { canMoveKnight, moveKnight } from "./Game.jsx";
import { ItemTypes } from "./Constants.jsx";
import { DropTarget } from "react-dnd";
const squareTarget = {
drop(props) {
moveKnight(props.x, props.y);
}
};
function collect(connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver()
};
}
export class BoardSquare extends Component {
render() {
const { x, y, connectDropTarget, isOver } = this.props;
const black = (x + y) % 2 === 1;
return connectDropTarget(
<div
style={{
position: "relative",
width: "100%",
height: "100%"
}}
>
<Square black={black}>{this.props.children}</Square>
{isOver && (
<div
style={{
position: "absolute",
top: 0,
left: 0,
height: "100%",
width: "100%",
zIndex: 1,
opacity: 0.5,
backgroundColor: "yellow"
}}
/>
)}
</div>
);
}
}
BoardSquare.propTypes = {
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
connectDropTarget: PropTypes.func.isRequired,
isOver: PropTypes.bool.isRequired
};
export default DropTarget(ItemTypes.KNIGHT, squareTarget, collect)(BoardSquare);
答案 0 :(得分:2)
您的错误是由此道具类型设置引起的:
BoardSquare.propTypes = {
// ...
connectDropTarget: PropTypes.func.isRequired,
// ^^^^^^^^^^^ property connectDropTarget is market as required
// ...
};
在connectDropTarget
中将BoardSquare
标记为必需的道具。
应该发生的是,因为您将BoardSquare
包裹在DropTarget
中,DropTarget
知道在connectDropTarget
的道具中设置BoardSquare
的值通过collect
函数。
但是,您所做的是使用准系统BoardSquare
功能,而不是DropTarget
中包含的功能。
// Board.jsx
import {BoardSquare} from './BoardSquare.jsx';
// ^ ^ you are importing BoardSquare, not DropTarget(...)(BoardSquare)
这应该是:
// Board.jsx
import BoardSquare from './BoardSquare.jsx';
因此,这意味着,由于您未使用DropTarget
中包含的组件,因此没有任何内容调用collect
函数,因此没有任何内容设置connectDropTarget
道具。< / p>
要清理内容,您可以从export
中移除准系统类的BoardSquare
,并仅导出DropTarget
中包含的类:
// BoardSquare.jsx
export class BoardSquare extends Component {
// ^^^ remove this export statement