我正在使用React DnD拖放项目。
在左侧,我有一个列表,如文本框,复选框,单选按钮等。当我开始拖动一个文本框并将其放在中间容器中时,它可以正常工作。
我在每次丢弃时都增加我的状态ID,例如状态:{id:"text1",name:""}
但是当我再次拖动相同的文本框并将其放到中间容器中时,我的状态正在获取重复值:例如state=[{id:"text2",name:""},{id:"text2",name:""}]
例如,当我多次放置一个项目时,我想要的实际输出是:
state=[{id:"text1",name:""},{id:"text2",name:""},{id:"text3",name:""}]
我搜索了所有react-dnd的示例...但是没有一个对我有帮助。
DummyData.tsx
import type from '../assets/images/type.png'
import paragraph from '../assets/images/paragraph.png'
import dropDownList from '../assets/images/drop-down-list.png'
import text from '../assets/images/text.png'
import checkbox from '../assets/images/checkbox.png'
import radioButton from '../assets/images/radio-button.png'
export const Controls = [
{
id: "text", label: "Text Field", fieldClass: "Text", category: "basic", image: type,
height: 30, width: 200, placeholder: "Enter your name", readOnly: false, disabled: false, required: false
}
, {
id: "textArea", label: "Text Area", fieldClass: "TextArea", category: "basic", image: text
}
, {
id: "dropdown", label: "Dropdown", fieldClass: "Select", category: "basic", image: dropDownList
}
, {
id: "radio", label: "Radio", fieldClass: "Radio", category: "basic", image: radioButton
}
, {
id: "checkbox", label: "Checkbox", fieldClass: "CheckBox", category: "basic", image: checkbox
}
, {
id: "paragraph", label: "Paragraph", fieldClass: "Paragraph", category: "basic", image: paragraph
}
]
ComponentDetails.tsx
import React, { Component } from 'react';
import { DragSource } from "react-dnd";
let count = 0;
interface ComponentDetailProps {
details: { id: string, label: string, fieldClass: string, category: string, image: string },
connectDragSource: any
}
class ComponentDetails extends Component<ComponentDetailProps, any> {
render() {
const { details, connectDragSource } = this.props;
return connectDragSource(<div className="boxStyle">{<div ><div style={{ textAlign: "center" }}>{<img src={details.image} width={25} />}</div><span className="nameStyle">{details.label}</span></div>}</div>);
}
}
function collect(connect: any) {
return {
connectDragSource: connect.dragSource()
};
}
const cardSource = {
beginDrag(props: any) {
const item = props.details;
return item;
}
};
export default DragSource("SOURCE", cardSource, collect)(ComponentDetails);
MainContiner.tsx
import React, { Component } from 'react';
import { Controls } from './DummyData';
import ComponentDetails from './ComponentDetails';
import MiddleContainer from './MiddleContainer';
import PopUp from './PopUp';
interface mainContainerState {
controlDetails: { id: string, label: string, fieldClass: string, category: string, image: string, height?: number, width?: number, placeholder?: string, disabled?: boolean, readOnly?: boolean, required?: boolean }[],
showModal: boolean,
individualDetails: { id: string, label: string, fieldClass: string, category: string, image: string, height?: number, width?: number, placeholder?: string, disabled?: boolean, readOnly?: boolean, required?: boolean },
index: number,
newObj: {}
}
class MainContainer extends Component<any, mainContainerState> {
constructor(props: any) {
super(props);
this.state = {
controlDetails: [{
id: "",
label: "",
fieldClass: "",
category: "",
image: "",
height: 0,
width: 0,
placeholder: "",
readOnly: false,
required: false,
disabled: false,
}],
showModal: false,
individualDetails: {
id: "",
label: "",
fieldClass: "",
category: "",
image: "",
height: 0,
width: 0,
placeholder: "",
readOnly: false,
required: false,
disabled: false
},
index: 0,
newObj: {}
}
}
onDrop = (newObj: any) => {
this.setState({ newObj });
console.log("5rrrr", this.state.newObj);
const allObjs: any = this.state.controlDetails;
console.log("DDDDDDDDDDD", allObjs);
this.setState({ controlDetails: [...allObjs, this.state.newObj] })
}
openModal = (de: any, index: number) => {
this.setState({ individualDetails: de });
this.setState({ showModal: true });
this.setState({ index: index });
}
handleCloseModal = () => {
this.setState({ showModal: false });
}
updatedControls = (updatedControls1: any) => {
if (this.state.index) {
const data1: any = [...this.state.controlDetails]
console.log("222222222222222", data1);
data1[this.state.index].placeholder = updatedControls1.placeholder;
this.setState({ controlDetails: data1 });
this.setState({ showModal: false });
} else {
console.log("111111111111111111111111");
}
}
render() {
console.log("SDssssssssssssss", this.state.controlDetails);
return (
<div className="container-fluid" style={{ padding: 0 }}>
<div className="row" style={{ height: "100vh", margin: 0 }}>
<div className="col-sm-3 px-1 bg-dark">
<div className="py-2 sticky-top flex-grow-1" style={{ padding: 10 }}>
<div className="nav flex-sm-column">
<h4 style={{ color: "#fff" }}>Controls</h4>
<div style={{
display: "flex",
flexWrap: "wrap",
}} >
{Controls.map((data) => {
return (
<div style={{
display: "block",
flex: "none",
width: `${100 / 3}%`,
boxSizing: "border-box",
}} >
<ComponentDetails details={data} />
</div>
)
})}
</div>
</div>
</div>
</div>
<div className="col" id="main" style={{
margin: 10,
borderRadius: 5,
padding: 10,
border: "1px solid #ddd",
background: "#fafafa"
}}>
<MiddleContainer onDrop={this.onDrop} controlDetails={this.state.controlDetails} openModal={this.openModal} />
</div>
</div>
<PopUp showModal={this.state.showModal} handleCloseModal={this.handleCloseModal}
individualDetails={this.state.individualDetails} updatedControls={this.updatedControls} />
</div>
)
}
}
export default MainContainer;
MiddleContainer.tsx
import React, { Component } from 'react';
import { DropTarget } from "react-dnd";
interface MiddleContainerProps {
connectDropTarget: any,
onDrop: (event: any) => void;
controlDetails: { id: string, label: string, fieldClass: string, category: string, image: string }[];
openModal: (event: any, index: number) => void;
}
let count = 0;
class MiddleContainer extends Component<MiddleContainerProps, any> {
constructor(props: MiddleContainerProps) {
super(props);
this.state = {
}
}
editClick = (details: any, index: number) => {
this.props.openModal(details, index);
}
render() {
const { connectDropTarget, controlDetails } = this.props;
return connectDropTarget(
<div>
Drop Items Here
<div >
{controlDetails.map((controlDetails: any, index: any) => {
return (
<div>
{<label >{controlDetails.label}</label>}
{controlDetails.fieldClass === "Text" ?
<div>
<input type="text" name={controlDetails.id}
readOnly={controlDetails.readOnly}
disabled={controlDetails.disabled}
placeholder={controlDetails.placeholder}
style={{
height: controlDetails.height, width: controlDetails.width,
}}
onChange={ev => this.setState({ [ev.target.name]: ev.target.value })}
/>
<button onClick={() => this.editClick(controlDetails, index)} >Edit</button>
</div>
: controlDetails.fieldClass === "TextArea" ? <div><textarea name={controlDetails.id} /></div>
: controlDetails.fieldClass === "Select" ? <div> <select
name={controlDetails.id} >
<option value="" disabled selected>Selected</option>
<option>one</option>
<option>two</option>
<option>three</option>
</select></div>
: controlDetails.fieldClass === "Radio" ? <div> <input type="radio" name={controlDetails.id} /></div>
: controlDetails.fieldClass === "CheckBox" ? <div> <input type="checkbox" name={controlDetails.id} /></div>
: controlDetails.fieldClass === "Paragraph" ? <div><textarea name={controlDetails.id} /></div> : ""}
</div>
)
})}
</div>
{this.state.text}
</div>
)
}
}
const spec = {
drop(props: any, monitor: any) {
const data = props.controlDetails.slice(-1)[0];
const item = monitor.getItem();
item["count"] = data.hasOwnProperty("count") ? data.count + 1 : count + 1;
props.onDrop(item);
}
};
function collect(connect: any, monitor: any) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
isOverCurrent: monitor.isOver({ shallow: true }),
canDrop: monitor.canDrop()
};
}
export default DropTarget("SOURCE", spec, collect)(MiddleContainer);
我正在得到这个:
state=[{id:"text2",name:""},{id:"text2",name:""}]
但是我想要的是:
state=[{id:"text1",name:""},{id:"text2",name:""}]