Я работаю над семейным деревом, где детей можно перевести к другим родителям. Проблема возникает, когда я переупорядочиваю семью с помощью перетаскивания (DnD), она не обновляется в объекте значений formik. Также, когда я удаляю дочерний элемент на DnD, он не обновляет объекты DnD, а обновляет объекты значений formik.
Ссылка Codesandbox: https://codesandbox.io/s/kind-hermann-lqve6 Ниже приведен код:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Formik, FieldArray } from "formik";
import { Button, Form } from "antd";
import { DndProvider } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import Sortly, { ContextProvider, useDrag, useDrop } from "react-sortly";
const FormItem = Form.Item;
const ItemRenderer = props => {
const {
index,
data: { text, kids }
} = props;
const [, drag] = useDrag();
const [, drop] = useDrop();
return (
<FieldArray
name="family.parents"
render={arrayHelpers => (
<div ref={drop} style={{ width: "40vw" }} key={index}>
<div
ref={drag}
style={{
padding: "0.5rem 1rem",
marginBottom: ".5rem",
backgroundColor: "green",
cursor: "move",
color: "white",
width: "320px"
}}
>
{`${text}`}
<FormItem style={{ display: "inline-block" }}>
<span className="parent-utility">
<Button
className="ant-btn"
shape="circle"
size="small"
style={{ color: "#ffa500" }}
onClick={() => arrayHelpers.remove(index)}
>
Delete
</Button>
</span>
</FormItem>
</div>
<KSortableTree kidsTree={kids} position={index} />
</div>
)}
/>
);
};
const ItemRendererA = props => {
const {
index,
position,
data: { text }
} = props;
const [, drag] = useDrag();
const [, drop] = useDrop();
return (
<FieldArray
name={`family.parents[${position}].kids`}
render={arrayHelpers => (
<>
<div ref={drop} style={{ width: "40vw" }}>
<div
ref={drag}
style={{
border: "1px dashed #70B5DC",
padding: "0.5rem 1rem",
marginBottom: ".5rem",
marginLeft: "3rem",
backgroundColor: "white",
cursor: "move",
color: "#70B5DC",
width: "17rem"
}}
>
{`${text}`}
<FormItem style={{ display: "inline-block" }}>
<span className="answer-utility">
<Button
className="ant-btn"
shape="circle"
size="small"
style={{ color: "#ffa500" }}
onClick={() => {
arrayHelpers.remove(index);
}}
>
Delete
</Button>
</span>
</FormItem>
</div>
</div>
</>
)}
/>
);
};
const PSortableTree = parentTree => {
const [items, setItems] = useState(parentTree.parentTree);
const handleChange = newItems => {
setItems(newItems);
};
return (
<Sortly items={items} onChange={handleChange}>
{props => <ItemRenderer {...props} />}
</Sortly>
);
};
const KSortableTree = kidsTree => {
const [itemsA, setItemsA] = useState(kidsTree.kidsTree);
const [positionA] = useState(kidsTree.position);
const handleChangeA = newItemsA => {
setItemsA(newItemsA);
};
return (
<Sortly items={itemsA} onChange={handleChangeA}>
{props => <ItemRendererA {...props} position={positionA} />}
</Sortly>
);
};
function FormDetail({ values, handleSubmit }) {
return (
<form onSubmit={handleSubmit}>
<h3>Family Tree</h3>
<DndProvider backend={HTML5Backend}>
<ContextProvider>
<PSortableTree parentTree={values.family.parents} />
</ContextProvider>
</DndProvider>
<div
style={{
padding: 16,
backgroundColor: "lightgrey",
borderRadius: "8px",
marginTop: "20px",
maxWidth: "100vw"
}}
>
{JSON.stringify(values)}
</div>
</form>
);
}
function App() {
return (
<Formik
enableReinitialize
initialValues={{
family: {
id: "2da80396",
parents: [
{
depth: 0,
id: "01a3b77c",
kids: [
{
depth: "1",
id: "01a3b77d",
text: "A",
correct: true
},
{
depth: "1",
id: "02fd6f62",
text: "C",
correct: false
}
],
text: "Parent 1"
},
{
depth: 0,
id: "773a4170",
kids: [
{
depth: "1",
id: "773a4171",
text: "A",
correct: false
},
{
depth: "1",
id: "773a4172",
text: "B",
correct: true
},
{
depth: "1",
id: "773a4173",
text: "C",
correct: false
}
],
text: "Parent 2"
},
{
depth: 0,
id: "a3652131",
kids: [
{
depth: "1",
id: "1c081c33",
text: "G",
correct: false
},
{
depth: "1",
id: "a3654842",
text: "A",
correct: true
},
{
depth: "1",
id: "a3654843",
text: "B",
correct: false
}
],
text: "Parent 3"
},
{
depth: 0,
id: "a3654845",
kids: [
{
depth: "1",
id: "a3654846",
text: "A",
correct: true
},
{
depth: "1",
id: "a3654847",
text: "B",
correct: false
}
],
text: "Parent 4"
},
{
depth: 0,
id: "eb3dc4d9",
kids: [
{
depth: "1",
id: "2103b3bc",
text: "D",
correct: true
},
{
depth: "1",
id: "28650f35",
text: "A",
correct: false
},
{
depth: "1",
id: "699584c2",
text: "B",
correct: false
},
{
depth: "1",
id: "a9edd5c4",
text: "C",
correct: false
}
],
text: "Parent 5"
}
],
text: "Heading"
}
}}
onSubmit={values => alert(JSON.stringify(values))}
component={FormDetail}
/>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);